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