
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 383 of file AVIFileSink.cpp.
References fBuffer, AVIFileSink::fBufferSize, fOurSink, fOurSourceIsActive, AVIFileSink::fPacketLossCompensate, fPrevBuffer, fPrevPresentationTime, NULL, MediaSubsession::readSource(), and subsession.
00385 : fOurSink(sink), fOurSubsession(subsession), 00386 fMaxBytesPerSecond(0), fIsVideo(False), fIsAudio(False), fIsByteSwappedAudio(False), fNumFrames(0) { 00387 fBuffer = new SubsessionBuffer(fOurSink.fBufferSize); 00388 fPrevBuffer = sink.fPacketLossCompensate 00389 ? new SubsessionBuffer(fOurSink.fBufferSize) : NULL; 00390 00391 FramedSource* subsessionSource = subsession.readSource(); 00392 fOurSourceIsActive = subsessionSource != NULL; 00393 00394 fPrevPresentationTime.tv_sec = 0; 00395 fPrevPresentationTime.tv_usec = 0; 00396 }
| AVISubsessionIOState::~AVISubsessionIOState | ( | ) | [virtual] |
Definition at line 398 of file AVIFileSink.cpp.
References fBuffer, and fPrevBuffer.
00398 { 00399 delete fBuffer; delete fPrevBuffer; 00400 }
| void AVISubsessionIOState::setAVIstate | ( | unsigned | subsessionIndex | ) |
Definition at line 402 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().
00402 { 00403 fIsVideo = strcmp(fOurSubsession.mediumName(), "video") == 0; 00404 fIsAudio = strcmp(fOurSubsession.mediumName(), "audio") == 0; 00405 00406 if (fIsVideo) { 00407 fAVISubsessionTag 00408 = fourChar('0'+subsessionIndex/10,'0'+subsessionIndex%10,'d','c'); 00409 if (strcmp(fOurSubsession.codecName(), "JPEG") == 0) { 00410 fAVICodecHandlerType = fourChar('m','j','p','g'); 00411 } else if (strcmp(fOurSubsession.codecName(), "MP4V-ES") == 0) { 00412 fAVICodecHandlerType = fourChar('D','I','V','X'); 00413 } else if (strcmp(fOurSubsession.codecName(), "MPV") == 0) { 00414 fAVICodecHandlerType = fourChar('m','p','g','1'); // what about MPEG-2? 00415 } else if (strcmp(fOurSubsession.codecName(), "H263-1998") == 0 || 00416 strcmp(fOurSubsession.codecName(), "H263-2000") == 0) { 00417 fAVICodecHandlerType = fourChar('H','2','6','3'); 00418 } else if (strcmp(fOurSubsession.codecName(), "H264") == 0) { 00419 fAVICodecHandlerType = fourChar('H','2','6','4'); 00420 } else { 00421 fAVICodecHandlerType = fourChar('?','?','?','?'); 00422 } 00423 fAVIScale = 1; // ??? ##### 00424 fAVIRate = fOurSink.fMovieFPS; // ??? ##### 00425 fAVISize = fOurSink.fMovieWidth*fOurSink.fMovieHeight*3; // ??? ##### 00426 } else if (fIsAudio) { 00427 fIsByteSwappedAudio = False; // by default 00428 fAVISubsessionTag 00429 = fourChar('0'+subsessionIndex/10,'0'+subsessionIndex%10,'w','b'); 00430 fAVICodecHandlerType = 1; // ??? #### 00431 unsigned numChannels = fOurSubsession.numChannels(); 00432 fAVISamplingFrequency = fOurSubsession.rtpTimestampFrequency(); // default 00433 if (strcmp(fOurSubsession.codecName(), "L16") == 0) { 00434 fIsByteSwappedAudio = True; // need to byte-swap data before writing it 00435 fWAVCodecTag = 0x0001; 00436 fAVIScale = fAVISize = 2*numChannels; // 2 bytes/sample 00437 fAVIRate = fAVISize*fAVISamplingFrequency; 00438 } else if (strcmp(fOurSubsession.codecName(), "L8") == 0) { 00439 fWAVCodecTag = 0x0001; 00440 fAVIScale = fAVISize = numChannels; // 1 byte/sample 00441 fAVIRate = fAVISize*fAVISamplingFrequency; 00442 } else if (strcmp(fOurSubsession.codecName(), "PCMA") == 0) { 00443 fWAVCodecTag = 0x0006; 00444 fAVIScale = fAVISize = numChannels; // 1 byte/sample 00445 fAVIRate = fAVISize*fAVISamplingFrequency; 00446 } else if (strcmp(fOurSubsession.codecName(), "PCMU") == 0) { 00447 fWAVCodecTag = 0x0007; 00448 fAVIScale = fAVISize = numChannels; // 1 byte/sample 00449 fAVIRate = fAVISize*fAVISamplingFrequency; 00450 } else if (strcmp(fOurSubsession.codecName(), "MPA") == 0) { 00451 fWAVCodecTag = 0x0050; 00452 fAVIScale = fAVISize = 1; 00453 fAVIRate = 0; // ??? ##### 00454 } else { 00455 fWAVCodecTag = 0x0001; // ??? ##### 00456 fAVIScale = fAVISize = 1; 00457 fAVIRate = 0; // ??? ##### 00458 } 00459 } else { // unknown medium 00460 fAVISubsessionTag 00461 = fourChar('0'+subsessionIndex/10,'0'+subsessionIndex%10,'?','?'); 00462 fAVICodecHandlerType = 0; 00463 fAVIScale = fAVISize = 1; 00464 fAVIRate = 0; // ??? ##### 00465 } 00466 }
| void AVISubsessionIOState::setFinalAVIstate | ( | ) |
| void AVISubsessionIOState::afterGettingFrame | ( | unsigned | packetDataSize, | |
| struct timeval | presentationTime | |||
| ) |
Definition at line 468 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().
00469 { 00470 // Begin by checking whether there was a gap in the RTP stream. 00471 // If so, try to compensate for this (if desired): 00472 unsigned short rtpSeqNum 00473 = fOurSubsession.rtpSource()->curPacketRTPSeqNum(); 00474 if (fOurSink.fPacketLossCompensate && fPrevBuffer->bytesInUse() > 0) { 00475 short seqNumGap = rtpSeqNum - fLastPacketRTPSeqNum; 00476 for (short i = 1; i < seqNumGap; ++i) { 00477 // Insert a copy of the previous frame, to compensate for the loss: 00478 useFrame(*fPrevBuffer); 00479 } 00480 } 00481 fLastPacketRTPSeqNum = rtpSeqNum; 00482 00483 // Now, continue working with the frame that we just got 00484 if (fBuffer->bytesInUse() == 0) { 00485 fBuffer->setPresentationTime(presentationTime); 00486 } 00487 fBuffer->addBytes(packetDataSize); 00488 00489 useFrame(*fBuffer); 00490 if (fOurSink.fPacketLossCompensate) { 00491 // Save this frame, in case we need it for recovery: 00492 SubsessionBuffer* tmp = fPrevBuffer; // assert: != NULL 00493 fPrevBuffer = fBuffer; 00494 fBuffer = tmp; 00495 } 00496 fBuffer->reset(); // for the next input 00497 00498 // Now, try getting more frames: 00499 fOurSink.continuePlaying(); 00500 }
| void AVISubsessionIOState::onSourceClosure | ( | ) |
Definition at line 554 of file AVIFileSink.cpp.
References False, fOurSink, fOurSourceIsActive, and AVIFileSink::onSourceClosure1().
Referenced by AVIFileSink::onRTCPBye(), and AVIFileSink::onSourceClosure().
00554 { 00555 fOurSourceIsActive = False; 00556 fOurSink.onSourceClosure1(); 00557 }
| 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 502 of file AVIFileSink.cpp.
References AVIFileSink::addByte(), AVIFileSink::addIndexRecord(), AVIFileSink::addWord(), SubsessionBuffer::bytesInUse(), MediaSubsession::codecName(), SubsessionBuffer::dataStart(), fAVISubsessionTag, fIsByteSwappedAudio, fMaxBytesPerSecond, AVIFileSink::fMoviSizePosition, AVIFileSink::fNumBytesWritten, fNumFrames, fourChar, fOurSink, fOurSubsession, AVIFileSink::fOutFid, fPrevPresentationTime, frameSize, and SubsessionBuffer::presentationTime().
Referenced by afterGettingFrame().
00502 { 00503 unsigned char* const frameSource = buffer.dataStart(); 00504 unsigned const frameSize = buffer.bytesInUse(); 00505 struct timeval const& presentationTime = buffer.presentationTime(); 00506 if (fPrevPresentationTime.tv_usec != 0||fPrevPresentationTime.tv_sec != 0) { 00507 int uSecondsDiff 00508 = (presentationTime.tv_sec - fPrevPresentationTime.tv_sec)*1000000 00509 + (presentationTime.tv_usec - fPrevPresentationTime.tv_usec); 00510 if (uSecondsDiff > 0) { 00511 unsigned bytesPerSecond = (unsigned)((frameSize*1000000.0)/uSecondsDiff); 00512 if (bytesPerSecond > fMaxBytesPerSecond) { 00513 fMaxBytesPerSecond = bytesPerSecond; 00514 } 00515 } 00516 } 00517 fPrevPresentationTime = presentationTime; 00518 00519 if (fIsByteSwappedAudio) { 00520 // We need to swap the 16-bit audio samples from big-endian 00521 // to little-endian order, before writing them to a file: 00522 for (unsigned i = 0; i < frameSize; i += 2) { 00523 unsigned char tmp = frameSource[i]; 00524 frameSource[i] = frameSource[i+1]; 00525 frameSource[i+1] = tmp; 00526 } 00527 } 00528 00529 // Add an index record for this frame: 00530 AVIIndexRecord* newIndexRecord 00531 = new AVIIndexRecord(fAVISubsessionTag, // chunk id 00532 frameSource[0] == 0x67 ? 0x10 : 0, // flags 00533 fOurSink.fMoviSizePosition + 8 + fOurSink.fNumBytesWritten, // offset (note: 8 == size + 'movi') 00534 frameSize + 4); // size 00535 fOurSink.addIndexRecord(newIndexRecord); 00536 00537 // Write the data into the file: 00538 fOurSink.fNumBytesWritten += fOurSink.addWord(fAVISubsessionTag); 00539 if (strcmp(fOurSubsession.codecName(), "H264") == 0) { 00540 // Insert a 'start code' (0x00 0x00 0x00 0x01) in front of the frame: 00541 fOurSink.fNumBytesWritten += fOurSink.addWord(4+frameSize); 00542 fOurSink.fNumBytesWritten += fOurSink.addWord(fourChar(0x00, 0x00, 0x00, 0x01));//add start code 00543 } else { 00544 fOurSink.fNumBytesWritten += fOurSink.addWord(frameSize); 00545 } 00546 fwrite(frameSource, 1, frameSize, fOurSink.fOutFid); 00547 fOurSink.fNumBytesWritten += frameSize; 00548 // Pad to an even length: 00549 if (frameSize%2 != 0) fOurSink.fNumBytesWritten += fOurSink.addByte(0); 00550 00551 ++fNumFrames; 00552 }
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(), setAVIstate(), and useFrame().
| 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