
Public Member Functions | |
| AVISubsessionIOState (AVIFileSink &sink, MediaSubsession &subsession) | |
| virtual | ~AVISubsessionIOState () |
| void | setAVIstate (unsigned subsessionIndex) |
| void | setFinalAVIstate () |
| void | afterGettingFrame (unsigned packetDataSize, struct timeval presentationTime) |
| void | onSourceClosure () |
| UsageEnvironment & | envir () const |
Data Fields | |
| SubsessionBuffer * | fBuffer |
| SubsessionBuffer * | fPrevBuffer |
| AVIFileSink & | fOurSink |
| MediaSubsession & | fOurSubsession |
| unsigned short | fLastPacketRTPSeqNum |
| Boolean | fOurSourceIsActive |
| timeval | fPrevPresentationTime |
| unsigned | fMaxBytesPerSecond |
| Boolean | fIsVideo |
| Boolean | fIsAudio |
| Boolean | fIsByteSwappedAudio |
| unsigned | fAVISubsessionTag |
| unsigned | fAVICodecHandlerType |
| unsigned | fAVISamplingFrequency |
| u_int16_t | fWAVCodecTag |
| unsigned | fAVIScale |
| unsigned | fAVIRate |
| unsigned | fAVISize |
| unsigned | fNumFrames |
| unsigned | fSTRHFrameCountPosition |
Private Member Functions | |
| void | useFrame (SubsessionBuffer &buffer) |
Definition at line 59 of file AVIFileSink.cpp.
| AVISubsessionIOState::AVISubsessionIOState | ( | AVIFileSink & | sink, | |
| MediaSubsession & | subsession | |||
| ) |
Definition at line 332 of file AVIFileSink.cpp.
References fBuffer, AVIFileSink::fBufferSize, fOurSink, fOurSourceIsActive, AVIFileSink::fPacketLossCompensate, fPrevBuffer, fPrevPresentationTime, NULL, MediaSubsession::readSource(), and subsession.
00334 : fOurSink(sink), fOurSubsession(subsession), 00335 fMaxBytesPerSecond(0), fIsVideo(False), fIsAudio(False), fIsByteSwappedAudio(False), fNumFrames(0) { 00336 fBuffer = new SubsessionBuffer(fOurSink.fBufferSize); 00337 fPrevBuffer = sink.fPacketLossCompensate 00338 ? new SubsessionBuffer(fOurSink.fBufferSize) : NULL; 00339 00340 FramedSource* subsessionSource = subsession.readSource(); 00341 fOurSourceIsActive = subsessionSource != NULL; 00342 00343 fPrevPresentationTime.tv_sec = 0; 00344 fPrevPresentationTime.tv_usec = 0; 00345 }
| AVISubsessionIOState::~AVISubsessionIOState | ( | ) | [virtual] |
Definition at line 347 of file AVIFileSink.cpp.
References fBuffer, and fPrevBuffer.
00347 { 00348 delete fBuffer; delete fPrevBuffer; 00349 }
| void AVISubsessionIOState::setAVIstate | ( | unsigned | subsessionIndex | ) |
Definition at line 351 of file AVIFileSink.cpp.
References MediaSubsession::codecName(), False, fAVICodecHandlerType, fAVIRate, fAVISamplingFrequency, fAVIScale, fAVISize, fAVISubsessionTag, fIsAudio, fIsByteSwappedAudio, fIsVideo, AVIFileSink::fMovieFPS, AVIFileSink::fMovieHeight, AVIFileSink::fMovieWidth, fourChar, fOurSink, fOurSubsession, fWAVCodecTag, MediaSubsession::mediumName(), MediaSubsession::numChannels(), MediaSubsession::rtpTimestampFrequency(), and True.
Referenced by while().
00351 { 00352 fIsVideo = strcmp(fOurSubsession.mediumName(), "video") == 0; 00353 fIsAudio = strcmp(fOurSubsession.mediumName(), "audio") == 0; 00354 00355 if (fIsVideo) { 00356 fAVISubsessionTag 00357 = fourChar('0'+subsessionIndex/10,'0'+subsessionIndex%10,'d','c'); 00358 if (strcmp(fOurSubsession.codecName(), "JPEG") == 0) { 00359 fAVICodecHandlerType = fourChar('m','j','p','g'); 00360 } else if (strcmp(fOurSubsession.codecName(), "MP4V-ES") == 0) { 00361 fAVICodecHandlerType = fourChar('D','I','V','X'); 00362 } else if (strcmp(fOurSubsession.codecName(), "MPV") == 0) { 00363 fAVICodecHandlerType = fourChar('m','p','g','1'); // what about MPEG-2? 00364 } else if (strcmp(fOurSubsession.codecName(), "H263-1998") == 0 || 00365 strcmp(fOurSubsession.codecName(), "H263-2000") == 0) { 00366 fAVICodecHandlerType = fourChar('H','2','6','3'); 00367 } else if (strcmp(fOurSubsession.codecName(), "H264") == 0) { 00368 fAVICodecHandlerType = fourChar('H','2','6','4'); 00369 } else { 00370 fAVICodecHandlerType = fourChar('?','?','?','?'); 00371 } 00372 fAVIScale = 1; // ??? ##### 00373 fAVIRate = fOurSink.fMovieFPS; // ??? ##### 00374 fAVISize = fOurSink.fMovieWidth*fOurSink.fMovieHeight*3; // ??? ##### 00375 } else if (fIsAudio) { 00376 fIsByteSwappedAudio = False; // by default 00377 fAVISubsessionTag 00378 = fourChar('0'+subsessionIndex/10,'0'+subsessionIndex%10,'w','b'); 00379 fAVICodecHandlerType = 1; // ??? #### 00380 unsigned numChannels = fOurSubsession.numChannels(); 00381 fAVISamplingFrequency = fOurSubsession.rtpTimestampFrequency(); // default 00382 if (strcmp(fOurSubsession.codecName(), "L16") == 0) { 00383 fIsByteSwappedAudio = True; // need to byte-swap data before writing it 00384 fWAVCodecTag = 0x0001; 00385 fAVIScale = fAVISize = 2*numChannels; // 2 bytes/sample 00386 fAVIRate = fAVISize*fAVISamplingFrequency; 00387 } else if (strcmp(fOurSubsession.codecName(), "L8") == 0) { 00388 fWAVCodecTag = 0x0001; 00389 fAVIScale = fAVISize = numChannels; // 1 byte/sample 00390 fAVIRate = fAVISize*fAVISamplingFrequency; 00391 } else if (strcmp(fOurSubsession.codecName(), "PCMA") == 0) { 00392 fWAVCodecTag = 0x0006; 00393 fAVIScale = fAVISize = numChannels; // 1 byte/sample 00394 fAVIRate = fAVISize*fAVISamplingFrequency; 00395 } else if (strcmp(fOurSubsession.codecName(), "PCMU") == 0) { 00396 fWAVCodecTag = 0x0007; 00397 fAVIScale = fAVISize = numChannels; // 1 byte/sample 00398 fAVIRate = fAVISize*fAVISamplingFrequency; 00399 } else if (strcmp(fOurSubsession.codecName(), "MPA") == 0) { 00400 fWAVCodecTag = 0x0050; 00401 fAVIScale = fAVISize = 1; 00402 fAVIRate = 0; // ??? ##### 00403 } else { 00404 fWAVCodecTag = 0x0001; // ??? ##### 00405 fAVIScale = fAVISize = 1; 00406 fAVIRate = 0; // ??? ##### 00407 } 00408 } else { // unknown medium 00409 fAVISubsessionTag 00410 = fourChar('0'+subsessionIndex/10,'0'+subsessionIndex%10,'?','?'); 00411 fAVICodecHandlerType = 0; 00412 fAVIScale = fAVISize = 1; 00413 fAVIRate = 0; // ??? ##### 00414 } 00415 }
| void AVISubsessionIOState::setFinalAVIstate | ( | ) |
| void AVISubsessionIOState::afterGettingFrame | ( | unsigned | packetDataSize, | |
| struct timeval | presentationTime | |||
| ) |
Definition at line 417 of file AVIFileSink.cpp.
References SubsessionBuffer::addBytes(), SubsessionBuffer::bytesInUse(), AVIFileSink::continuePlaying(), RTPSource::curPacketRTPSeqNum(), fBuffer, fLastPacketRTPSeqNum, fOurSink, fOurSubsession, AVIFileSink::fPacketLossCompensate, fPrevBuffer, SubsessionBuffer::reset(), MediaSubsession::rtpSource(), SubsessionBuffer::setPresentationTime(), and useFrame().
Referenced by AVIFileSink::afterGettingFrame().
00418 { 00419 // Begin by checking whether there was a gap in the RTP stream. 00420 // If so, try to compensate for this (if desired): 00421 unsigned short rtpSeqNum 00422 = fOurSubsession.rtpSource()->curPacketRTPSeqNum(); 00423 if (fOurSink.fPacketLossCompensate && fPrevBuffer->bytesInUse() > 0) { 00424 short seqNumGap = rtpSeqNum - fLastPacketRTPSeqNum; 00425 for (short i = 1; i < seqNumGap; ++i) { 00426 // Insert a copy of the previous frame, to compensate for the loss: 00427 useFrame(*fPrevBuffer); 00428 } 00429 } 00430 fLastPacketRTPSeqNum = rtpSeqNum; 00431 00432 // Now, continue working with the frame that we just got 00433 if (fBuffer->bytesInUse() == 0) { 00434 fBuffer->setPresentationTime(presentationTime); 00435 } 00436 fBuffer->addBytes(packetDataSize); 00437 00438 useFrame(*fBuffer); 00439 if (fOurSink.fPacketLossCompensate) { 00440 // Save this frame, in case we need it for recovery: 00441 SubsessionBuffer* tmp = fPrevBuffer; // assert: != NULL 00442 fPrevBuffer = fBuffer; 00443 fBuffer = tmp; 00444 } 00445 fBuffer->reset(); // for the next input 00446 00447 // Now, try getting more frames: 00448 fOurSink.continuePlaying(); 00449 }
| void AVISubsessionIOState::onSourceClosure | ( | ) |
Definition at line 489 of file AVIFileSink.cpp.
References False, fOurSink, fOurSourceIsActive, and AVIFileSink::onSourceClosure1().
Referenced by AVIFileSink::onRTCPBye(), and AVIFileSink::onSourceClosure().
00489 { 00490 fOurSourceIsActive = False; 00491 fOurSink.onSourceClosure1(); 00492 }
| UsageEnvironment& AVISubsessionIOState::envir | ( | ) | const [inline] |
Definition at line 71 of file AVIFileSink.cpp.
References Medium::envir(), and fOurSink.
Referenced by AVIFileSink::afterGettingFrame(), and AVIFileSink::onRTCPBye().
| void AVISubsessionIOState::useFrame | ( | SubsessionBuffer & | buffer | ) | [private] |
Definition at line 451 of file AVIFileSink.cpp.
References AVIFileSink::addByte(), AVIFileSink::addWord(), SubsessionBuffer::bytesInUse(), SubsessionBuffer::dataStart(), fAVISubsessionTag, fIsByteSwappedAudio, fMaxBytesPerSecond, AVIFileSink::fNumBytesWritten, fNumFrames, fOurSink, AVIFileSink::fOutFid, fPrevPresentationTime, frameSize, and SubsessionBuffer::presentationTime().
Referenced by afterGettingFrame().
00451 { 00452 unsigned char* const frameSource = buffer.dataStart(); 00453 unsigned const frameSize = buffer.bytesInUse(); 00454 struct timeval const& presentationTime = buffer.presentationTime(); 00455 if (fPrevPresentationTime.tv_usec != 0||fPrevPresentationTime.tv_sec != 0) { 00456 int uSecondsDiff 00457 = (presentationTime.tv_sec - fPrevPresentationTime.tv_sec)*1000000 00458 + (presentationTime.tv_usec - fPrevPresentationTime.tv_usec); 00459 if (uSecondsDiff > 0) { 00460 unsigned bytesPerSecond = (unsigned)((frameSize*1000000.0)/uSecondsDiff); 00461 if (bytesPerSecond > fMaxBytesPerSecond) { 00462 fMaxBytesPerSecond = bytesPerSecond; 00463 } 00464 } 00465 } 00466 fPrevPresentationTime = presentationTime; 00467 00468 if (fIsByteSwappedAudio) { 00469 // We need to swap the 16-bit audio samples from big-endian 00470 // to little-endian order, before writing them to a file: 00471 for (unsigned i = 0; i < frameSize; i += 2) { 00472 unsigned char tmp = frameSource[i]; 00473 frameSource[i] = frameSource[i+1]; 00474 frameSource[i+1] = tmp; 00475 } 00476 } 00477 00478 // Write the data into the file: 00479 fOurSink.fNumBytesWritten += fOurSink.addWord(fAVISubsessionTag); 00480 fOurSink.fNumBytesWritten += fOurSink.addWord(frameSize); 00481 fwrite(frameSource, 1, frameSize, fOurSink.fOutFid); 00482 fOurSink.fNumBytesWritten += frameSize; 00483 // Pad to an even length: 00484 if (frameSize%2 != 0) fOurSink.fNumBytesWritten += fOurSink.addByte(0); 00485 00486 ++fNumFrames; 00487 }
Definition at line 74 of file AVIFileSink.cpp.
Referenced by afterGettingFrame(), AVISubsessionIOState(), AVIFileSink::continuePlaying(), and ~AVISubsessionIOState().
Definition at line 74 of file AVIFileSink.cpp.
Referenced by afterGettingFrame(), AVISubsessionIOState(), and ~AVISubsessionIOState().
Definition at line 75 of file AVIFileSink.cpp.
Referenced by afterGettingFrame(), AVISubsessionIOState(), envir(), AVIFileSink::onRTCPBye(), onSourceClosure(), setAVIstate(), and useFrame().
Definition at line 76 of file AVIFileSink.cpp.
Referenced by afterGettingFrame(), AVIFileSink::onRTCPBye(), and setAVIstate().
| unsigned short AVISubsessionIOState::fLastPacketRTPSeqNum |
Definition at line 79 of file AVIFileSink.cpp.
Referenced by AVISubsessionIOState(), onSourceClosure(), and AVIFileSink::onSourceClosure1().
struct timeval AVISubsessionIOState::fPrevPresentationTime [read] |
Definition at line 80 of file AVIFileSink.cpp.
Referenced by AVISubsessionIOState(), and useFrame().
Definition at line 81 of file AVIFileSink.cpp.
Referenced by AVIFileSink::completeOutputFile(), and useFrame().
Definition at line 82 of file AVIFileSink.cpp.
Referenced by AVIFileSink::completeOutputFile(), and setAVIstate().
Definition at line 82 of file AVIFileSink.cpp.
Referenced by AVIFileSink::completeOutputFile(), and setAVIstate().
| u_int16_t AVISubsessionIOState::fWAVCodecTag |
| unsigned AVISubsessionIOState::fAVIScale |
| unsigned AVISubsessionIOState::fAVIRate |
| unsigned AVISubsessionIOState::fAVISize |
| unsigned AVISubsessionIOState::fNumFrames |
Definition at line 90 of file AVIFileSink.cpp.
Referenced by AVIFileSink::completeOutputFile(), and useFrame().
1.5.2