
Definition at line 97 of file QuickTimeFileSink.cpp.
| typedef unsigned(QuickTimeFileSink::*) SubsessionIOState::atomCreationFunc() |
Definition at line 137 of file QuickTimeFileSink.cpp.
| SubsessionIOState::SubsessionIOState | ( | QuickTimeFileSink & | sink, | |
| MediaSubsession & | subsession | |||
| ) |
Definition at line 507 of file QuickTimeFileSink.cpp.
References fBuffer, QuickTimeFileSink::fBufferSize, fCurrentTrackNumber, fOurSink, fOurSourceIsActive, QuickTimeFileSink::fPacketLossCompensate, fPrevBuffer, fPrevFrameState, fTrackID, NULL, MediaSubsession::readSource(), and subsession.
00509 : fHintTrackForUs(NULL), fTrackHintedByUs(NULL), 00510 fOurSink(sink), fOurSubsession(subsession), 00511 fLastPacketRTPSeqNum(0), fHaveBeenSynced(False), fQTTotNumSamples(0), 00512 fHeadChunk(NULL), fTailChunk(NULL), fNumChunks(0) { 00513 fTrackID = ++fCurrentTrackNumber; 00514 00515 fBuffer = new SubsessionBuffer(fOurSink.fBufferSize); 00516 fPrevBuffer = sink.fPacketLossCompensate 00517 ? new SubsessionBuffer(fOurSink.fBufferSize) : NULL; 00518 00519 FramedSource* subsessionSource = subsession.readSource(); 00520 fOurSourceIsActive = subsessionSource != NULL; 00521 00522 fPrevFrameState.presentationTime.tv_sec = 0; 00523 fPrevFrameState.presentationTime.tv_usec = 0; 00524 fPrevFrameState.seqNum = 0; 00525 }
| SubsessionIOState::~SubsessionIOState | ( | ) | [virtual] |
Definition at line 527 of file QuickTimeFileSink.cpp.
References fBuffer, fHeadChunk, and fPrevBuffer.
00527 { 00528 delete fBuffer; delete fPrevBuffer; 00529 delete fHeadChunk; 00530 }
| Boolean SubsessionIOState::setQTstate | ( | ) |
Definition at line 532 of file QuickTimeFileSink.cpp.
References QuickTimeFileSink::addAtom_dummy(), QuickTimeFileSink::addAtom_genericMedia(), QuickTimeFileSink::addAtom_soundMediaGeneral(), MediaSubsession::codecName(), envir(), False, QuickTimeFileSink::fMovieFPS, MediaSubsession::fmtp_config(), fourChar, fOurSink, fOurSubsession, fQTAudioDataType, fQTBytesPerFrame, fQTcomponentName, fQTcomponentSubtype, fQTEnableTrack, fQTMediaDataAtomCreator, fQTMediaInformationAtomCreator, fQTSamplesPerFrame, fQTSoundSampleVersion, fQTTimeScale, fQTTimeUnitsPerSample, isHintTrack(), MediaSubsession::mediumName(), MediaSubsession::rtpTimestampFrequency(), samplingFrequencyFromAudioSpecificConfig(), and True.
Referenced by QuickTimeFileSink::QuickTimeFileSink().
00532 { 00533 char const* noCodecWarning1 = "Warning: We don't implement a QuickTime "; 00534 char const* noCodecWarning2 = " Media Data Type for the \""; 00535 char const* noCodecWarning3 = "\" track, so we'll insert a dummy \"????\" Media Data Atom instead. A separate, codec-specific editing pass will be needed before this track can be played.\n"; 00536 00537 do { 00538 fQTEnableTrack = True; // enable this track in the movie by default 00539 fQTTimeScale = fOurSubsession.rtpTimestampFrequency(); // by default 00540 fQTTimeUnitsPerSample = 1; // by default 00541 fQTBytesPerFrame = 0; 00542 // by default - indicates that the whole packet data is a frame 00543 fQTSamplesPerFrame = 1; // by default 00544 00545 // Make sure our subsession's medium is one that we know how to 00546 // represent in a QuickTime file: 00547 if (isHintTrack()) { 00548 // Hint tracks are treated specially 00549 fQTEnableTrack = False; // hint tracks are marked as inactive 00550 fQTcomponentSubtype = fourChar('h','i','n','t'); 00551 fQTcomponentName = "hint media handler"; 00552 fQTMediaInformationAtomCreator = &QuickTimeFileSink::addAtom_gmhd; 00553 fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_rtp; 00554 } else if (strcmp(fOurSubsession.mediumName(), "audio") == 0) { 00555 fQTcomponentSubtype = fourChar('s','o','u','n'); 00556 fQTcomponentName = "Apple Sound Media Handler"; 00557 fQTMediaInformationAtomCreator = &QuickTimeFileSink::addAtom_smhd; 00558 fQTMediaDataAtomCreator 00559 = &QuickTimeFileSink::addAtom_soundMediaGeneral; // by default 00560 fQTSoundSampleVersion = 0; // by default 00561 00562 // Make sure that our subsession's codec is one that we can handle: 00563 if (strcmp(fOurSubsession.codecName(), "X-QT") == 0 || 00564 strcmp(fOurSubsession.codecName(), "X-QUICKTIME") == 0) { 00565 fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_genericMedia; 00566 } else if (strcmp(fOurSubsession.codecName(), "PCMU") == 0) { 00567 fQTAudioDataType = "ulaw"; 00568 fQTBytesPerFrame = 1; 00569 } else if (strcmp(fOurSubsession.codecName(), "GSM") == 0) { 00570 fQTAudioDataType = "agsm"; 00571 fQTBytesPerFrame = 33; 00572 fQTSamplesPerFrame = 160; 00573 } else if (strcmp(fOurSubsession.codecName(), "PCMA") == 0) { 00574 fQTAudioDataType = "alaw"; 00575 fQTBytesPerFrame = 1; 00576 } else if (strcmp(fOurSubsession.codecName(), "QCELP") == 0) { 00577 fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_Qclp; 00578 fQTSamplesPerFrame = 160; 00579 } else if (strcmp(fOurSubsession.codecName(), "MPEG4-GENERIC") == 0 || 00580 strcmp(fOurSubsession.codecName(), "MP4A-LATM") == 0) { 00581 fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_mp4a; 00582 fQTTimeUnitsPerSample = 1024; // QT considers each frame to be a 'sample' 00583 // The time scale (frequency) comes from the 'config' information. 00584 // It might be different from the RTP timestamp frequency (e.g., aacPlus). 00585 unsigned frequencyFromConfig 00586 = samplingFrequencyFromAudioSpecificConfig(fOurSubsession.fmtp_config()); 00587 if (frequencyFromConfig != 0) fQTTimeScale = frequencyFromConfig; 00588 } else { 00589 envir() << noCodecWarning1 << "Audio" << noCodecWarning2 00590 << fOurSubsession.codecName() << noCodecWarning3; 00591 fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_dummy; 00592 fQTEnableTrack = False; // disable this track in the movie 00593 } 00594 } else if (strcmp(fOurSubsession.mediumName(), "video") == 0) { 00595 fQTcomponentSubtype = fourChar('v','i','d','e'); 00596 fQTcomponentName = "Apple Video Media Handler"; 00597 fQTMediaInformationAtomCreator = &QuickTimeFileSink::addAtom_vmhd; 00598 00599 // Make sure that our subsession's codec is one that we can handle: 00600 if (strcmp(fOurSubsession.codecName(), "X-QT") == 0 || 00601 strcmp(fOurSubsession.codecName(), "X-QUICKTIME") == 0) { 00602 fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_genericMedia; 00603 } else if (strcmp(fOurSubsession.codecName(), "H263-1998") == 0 || 00604 strcmp(fOurSubsession.codecName(), "H263-2000") == 0) { 00605 fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_h263; 00606 fQTTimeScale = 600; 00607 fQTTimeUnitsPerSample = fQTTimeScale/fOurSink.fMovieFPS; 00608 } else if (strcmp(fOurSubsession.codecName(), "H264") == 0) { 00609 fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_avc1; 00610 fQTTimeScale = 600; 00611 fQTTimeUnitsPerSample = fQTTimeScale/fOurSink.fMovieFPS; 00612 } else if (strcmp(fOurSubsession.codecName(), "MP4V-ES") == 0) { 00613 fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_mp4v; 00614 fQTTimeScale = 600; 00615 fQTTimeUnitsPerSample = fQTTimeScale/fOurSink.fMovieFPS; 00616 } else { 00617 envir() << noCodecWarning1 << "Video" << noCodecWarning2 00618 << fOurSubsession.codecName() << noCodecWarning3; 00619 fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_dummy; 00620 fQTEnableTrack = False; // disable this track in the movie 00621 } 00622 } else { 00623 envir() << "Warning: We don't implement a QuickTime Media Handler for media type \"" 00624 << fOurSubsession.mediumName() << "\""; 00625 break; 00626 } 00627 00628 #ifdef QT_SUPPORT_PARTIALLY_ONLY 00629 envir() << "Warning: We don't have sufficient codec-specific information (e.g., sample sizes) to fully generate the \"" 00630 << fOurSubsession.mediumName() << "/" << fOurSubsession.codecName() 00631 << "\" track, so we'll disable this track in the movie. A separate, codec-specific editing pass will be needed before this track can be played\n"; 00632 fQTEnableTrack = False; // disable this track in the movie 00633 #endif 00634 00635 return True; 00636 } while (0); 00637 00638 envir() << ", so a track for the \"" << fOurSubsession.mediumName() 00639 << "/" << fOurSubsession.codecName() 00640 << "\" subsession will not be included in the output QuickTime file\n"; 00641 return False; 00642 }
| void SubsessionIOState::setFinalQTstate | ( | ) |
Definition at line 644 of file QuickTimeFileSink.cpp.
References chunk, ChunkDescriptor::fFrameDuration, fHeadChunk, QuickTimeFileSink::fMaxTrackDurationM, ChunkDescriptor::fNextChunk, ChunkDescriptor::fNumFrames, fOurSink, fQTDurationM, fQTDurationT, fQTTimeScale, QuickTimeFileSink::movieTimeScale(), and NULL.
Referenced by QuickTimeFileSink::completeOutputFile().
00644 { 00645 // Compute derived parameters, by running through the list of chunks: 00646 fQTDurationT = 0; 00647 00648 ChunkDescriptor* chunk = fHeadChunk; 00649 while (chunk != NULL) { 00650 unsigned const numFrames = chunk->fNumFrames; 00651 unsigned const dur = numFrames*chunk->fFrameDuration; 00652 fQTDurationT += dur; 00653 00654 chunk = chunk->fNextChunk; 00655 } 00656 00657 // Convert this duration from track to movie time scale: 00658 double scaleFactor = fOurSink.movieTimeScale()/(double)fQTTimeScale; 00659 fQTDurationM = (unsigned)(fQTDurationT*scaleFactor); 00660 00661 if (fQTDurationM > fOurSink.fMaxTrackDurationM) { 00662 fOurSink.fMaxTrackDurationM = fQTDurationM; 00663 } 00664 }
| void SubsessionIOState::afterGettingFrame | ( | unsigned | packetDataSize, | |
| struct timeval | presentationTime | |||
| ) |
Definition at line 666 of file QuickTimeFileSink.cpp.
References QuickTimeFileSink::addAtom_genericMedia(), SubsessionBuffer::addBytes(), SubsessionBuffer::bytesInUse(), QuickTimeFileSink::continuePlaying(), RTPSource::curPacketRTPSeqNum(), fBuffer, fLastPacketRTPSeqNum, QuickTimeFileSink::fMovieFPS, QuickTimeFileSink::fMovieHeight, QuickTimeFileSink::fMovieWidth, fourChar, fOurSink, fOurSubsession, QuickTimeFileSink::fPacketLossCompensate, fPrevBuffer, fQTBytesPerFrame, fQTMediaDataAtomCreator, fQTSamplesPerFrame, fQTTimeScale, fQTTimeUnitsPerSample, QuickTimeGenericRTPSource::QTState::height, QuickTimeGenericRTPSource::qtState, SubsessionBuffer::reset(), MediaSubsession::rtpSource(), QuickTimeGenericRTPSource::QTState::sdAtom, QuickTimeGenericRTPSource::QTState::sdAtomSize, SubsessionBuffer::setPresentationTime(), QuickTimeGenericRTPSource::QTState::timescale, useFrame(), and QuickTimeGenericRTPSource::QTState::width.
Referenced by QuickTimeFileSink::afterGettingFrame().
00667 { 00668 // Begin by checking whether there was a gap in the RTP stream. 00669 // If so, try to compensate for this (if desired): 00670 unsigned short rtpSeqNum 00671 = fOurSubsession.rtpSource()->curPacketRTPSeqNum(); 00672 if (fOurSink.fPacketLossCompensate && fPrevBuffer->bytesInUse() > 0) { 00673 short seqNumGap = rtpSeqNum - fLastPacketRTPSeqNum; 00674 for (short i = 1; i < seqNumGap; ++i) { 00675 // Insert a copy of the previous frame, to compensate for the loss: 00676 useFrame(*fPrevBuffer); 00677 } 00678 } 00679 fLastPacketRTPSeqNum = rtpSeqNum; 00680 00681 // Now, continue working with the frame that we just got 00682 if (fBuffer->bytesInUse() == 0) { 00683 fBuffer->setPresentationTime(presentationTime); 00684 } 00685 fBuffer->addBytes(packetDataSize); 00686 00687 // If our RTP source is a "QuickTimeGenericRTPSource", then 00688 // use its 'qtState' to set some parameters that we need: 00689 if (fQTMediaDataAtomCreator == &QuickTimeFileSink::addAtom_genericMedia){ 00690 QuickTimeGenericRTPSource* rtpSource 00691 = (QuickTimeGenericRTPSource*)fOurSubsession.rtpSource(); 00692 QuickTimeGenericRTPSource::QTState& qtState = rtpSource->qtState; 00693 fQTTimeScale = qtState.timescale; 00694 if (qtState.width != 0) { 00695 fOurSink.fMovieWidth = qtState.width; 00696 } 00697 if (qtState.height != 0) { 00698 fOurSink.fMovieHeight = qtState.height; 00699 } 00700 00701 // Also, if the media type in the "sdAtom" is one that we recognize 00702 // to have a special parameters, then fix this here: 00703 if (qtState.sdAtomSize >= 8) { 00704 char const* atom = qtState.sdAtom; 00705 unsigned mediaType = fourChar(atom[4],atom[5],atom[6],atom[7]); 00706 switch (mediaType) { 00707 case fourChar('a','g','s','m'): { 00708 fQTBytesPerFrame = 33; 00709 fQTSamplesPerFrame = 160; 00710 break; 00711 } 00712 case fourChar('Q','c','l','p'): { 00713 fQTBytesPerFrame = 35; 00714 fQTSamplesPerFrame = 160; 00715 break; 00716 } 00717 case fourChar('H','c','l','p'): { 00718 fQTBytesPerFrame = 17; 00719 fQTSamplesPerFrame = 160; 00720 break; 00721 } 00722 case fourChar('h','2','6','3'): { 00723 fQTTimeUnitsPerSample = fQTTimeScale/fOurSink.fMovieFPS; 00724 break; 00725 } 00726 } 00727 } 00728 } else if (fQTMediaDataAtomCreator == &QuickTimeFileSink::addAtom_Qclp) { 00729 // For QCELP data, make a note of the frame size (even though it's the 00730 // same as the packet data size), because it varies depending on the 00731 // 'rate' of the stream, and this size gets used later when setting up 00732 // the 'Qclp' QuickTime atom: 00733 fQTBytesPerFrame = packetDataSize; 00734 } 00735 00736 useFrame(*fBuffer); 00737 if (fOurSink.fPacketLossCompensate) { 00738 // Save this frame, in case we need it for recovery: 00739 SubsessionBuffer* tmp = fPrevBuffer; // assert: != NULL 00740 fPrevBuffer = fBuffer; 00741 fBuffer = tmp; 00742 } 00743 fBuffer->reset(); // for the next input 00744 00745 // Now, try getting more frames: 00746 fOurSink.continuePlaying(); 00747 }
| void SubsessionIOState::onSourceClosure | ( | ) |
Definition at line 1042 of file QuickTimeFileSink.cpp.
References False, fOurSink, fOurSourceIsActive, and QuickTimeFileSink::onSourceClosure1().
Referenced by QuickTimeFileSink::onRTCPBye(), and QuickTimeFileSink::onSourceClosure().
01042 { 01043 fOurSourceIsActive = False; 01044 fOurSink.onSourceClosure1(); 01045 }
| Boolean SubsessionIOState::syncOK | ( | struct timeval | presentationTime | ) |
Definition at line 1047 of file QuickTimeFileSink.cpp.
References False, fHaveBeenSynced, QuickTimeFileSink::fNumSubsessions, QuickTimeFileSink::fNumSyncedSubsessions, fOurSink, fOurSubsession, QuickTimeFileSink::fSyncStreams, fSyncTime, RTPSource::hasBeenSynchronizedUsingRTCP(), MediaSubsession::rtpSource(), timevalGE(), and True.
Referenced by QuickTimeFileSink::afterGettingFrame().
01047 { 01048 QuickTimeFileSink& s = fOurSink; // abbreviation 01049 if (!s.fSyncStreams) return True; // we don't care 01050 01051 if (s.fNumSyncedSubsessions < s.fNumSubsessions) { 01052 // Not all subsessions have yet been synced. Check whether ours was 01053 // one of the unsynced ones, and, if so, whether it is now synced: 01054 if (!fHaveBeenSynced) { 01055 // We weren't synchronized before 01056 if (fOurSubsession.rtpSource()->hasBeenSynchronizedUsingRTCP()) { 01057 // But now we are 01058 fHaveBeenSynced = True; 01059 fSyncTime = presentationTime; 01060 ++s.fNumSyncedSubsessions; 01061 01062 if (timevalGE(fSyncTime, s.fNewestSyncTime)) { 01063 s.fNewestSyncTime = fSyncTime; 01064 } 01065 } 01066 } 01067 } 01068 01069 // Check again whether all subsessions have been synced: 01070 if (s.fNumSyncedSubsessions < s.fNumSubsessions) return False; 01071 01072 // Allow this data if it is more recent than the newest sync time: 01073 return timevalGE(presentationTime, s.fNewestSyncTime); 01074 }
| void SubsessionIOState::setHintTrack | ( | SubsessionIOState * | hintedTrack, | |
| SubsessionIOState * | hintTrack | |||
| ) | [static] |
Definition at line 1076 of file QuickTimeFileSink.cpp.
References fHintTrackForUs, fTrackHintedByUs, hintedTrack, and NULL.
Referenced by QuickTimeFileSink::QuickTimeFileSink().
01077 { 01078 if (hintedTrack != NULL) hintedTrack->fHintTrackForUs = hintTrack; 01079 if (hintTrack != NULL) hintTrack->fTrackHintedByUs = hintedTrack; 01080 }
| Boolean SubsessionIOState::isHintTrack | ( | ) | const [inline] |
Definition at line 114 of file QuickTimeFileSink.cpp.
References fTrackHintedByUs, and NULL.
Referenced by QuickTimeFileSink::addAtom_hdlr2(), and setQTstate().
00114 { return fTrackHintedByUs != NULL; }
| Boolean SubsessionIOState::hasHintTrack | ( | ) | const [inline] |
Definition at line 115 of file QuickTimeFileSink.cpp.
References fHintTrackForUs, and NULL.
Referenced by QuickTimeFileSink::completeOutputFile(), useFrame(), and while().
00115 { return fHintTrackForUs != NULL; }
| UsageEnvironment& SubsessionIOState::envir | ( | ) | const [inline] |
Definition at line 117 of file QuickTimeFileSink.cpp.
References Medium::envir(), and fOurSink.
Referenced by QuickTimeFileSink::onRTCPBye(), setQTstate(), and useFrameForHinting().
| void SubsessionIOState::useFrame | ( | SubsessionBuffer & | buffer | ) | [private] |
Definition at line 749 of file QuickTimeFileSink.cpp.
References QuickTimeFileSink::addWord(), SubsessionBuffer::bytesInUse(), SubsessionBuffer::dataStart(), destFileOffset, duration, fHaveBeenSynced, fHintTrackForUs, fourChar, fOurSink, fOurSubsession, QuickTimeFileSink::fOutFid, fPrevFrameState, fQTcomponentSubtype, fQTMediaDataAtomCreator, fQTSamplesPerFrame, fQTTimeScale, fQTTimeUnitsPerSample, fQTTotNumSamples, frameSize, QuickTimeFileSink::fSyncStreams, RTPSource::hasBeenSynchronizedUsingRTCP(), hasHintTrack(), SubsessionBuffer::presentationTime(), presentationTime, MediaSubsession::rtpSource(), useFrame1(), and useFrameForHinting().
Referenced by afterGettingFrame().
00749 { 00750 unsigned char* const frameSource = buffer.dataStart(); 00751 unsigned const frameSize = buffer.bytesInUse(); 00752 struct timeval const& presentationTime = buffer.presentationTime(); 00753 unsigned const destFileOffset = ftell(fOurSink.fOutFid); 00754 unsigned sampleNumberOfFrameStart = fQTTotNumSamples + 1; 00755 Boolean avcHack = fQTMediaDataAtomCreator == &QuickTimeFileSink::addAtom_avc1; 00756 00757 // If we're not syncing streams, or this subsession is not video, then 00758 // just give this frame a fixed duration: 00759 if (!fOurSink.fSyncStreams 00760 || fQTcomponentSubtype != fourChar('v','i','d','e')) { 00761 unsigned const frameDuration = fQTTimeUnitsPerSample*fQTSamplesPerFrame; 00762 unsigned frameSizeToUse = frameSize; 00763 if (avcHack) frameSizeToUse += 4; // H.264/AVC gets the frame size prefix 00764 00765 fQTTotNumSamples += useFrame1(frameSizeToUse, presentationTime, frameDuration, destFileOffset); 00766 } else { 00767 // For synced video streams, we use the difference between successive 00768 // frames' presentation times as the 'frame duration'. So, record 00769 // information about the *previous* frame: 00770 struct timeval const& ppt = fPrevFrameState.presentationTime; //abbrev 00771 if (ppt.tv_sec != 0 || ppt.tv_usec != 0) { 00772 // There has been a previous frame. 00773 double duration = (presentationTime.tv_sec - ppt.tv_sec) 00774 + (presentationTime.tv_usec - ppt.tv_usec)/1000000.0; 00775 if (duration < 0.0) duration = 0.0; 00776 unsigned frameDuration 00777 = (unsigned)((2*duration*fQTTimeScale+1)/2); // round 00778 unsigned frameSizeToUse = fPrevFrameState.frameSize; 00779 if (avcHack) frameSizeToUse += 4; // H.264/AVC gets the frame size prefix 00780 00781 unsigned numSamples 00782 = useFrame1(frameSizeToUse, ppt, frameDuration, fPrevFrameState.destFileOffset); 00783 fQTTotNumSamples += numSamples; 00784 sampleNumberOfFrameStart = fQTTotNumSamples + 1; 00785 } 00786 00787 // Remember the current frame for next time: 00788 fPrevFrameState.frameSize = frameSize; 00789 fPrevFrameState.presentationTime = presentationTime; 00790 fPrevFrameState.destFileOffset = destFileOffset; 00791 } 00792 00793 if (avcHack) fOurSink.addWord(frameSize); 00794 00795 // Write the data into the file: 00796 fwrite(frameSource, 1, frameSize, fOurSink.fOutFid); 00797 00798 // If we have a hint track, then write to it also: 00799 if (hasHintTrack()) { 00800 // Because presentation times are used for RTP packet timestamps, 00801 // we don't starting writing to the hint track until we've been synced: 00802 if (!fHaveBeenSynced) { 00803 fHaveBeenSynced 00804 = fOurSubsession.rtpSource()->hasBeenSynchronizedUsingRTCP(); 00805 } 00806 if (fHaveBeenSynced) { 00807 fHintTrackForUs->useFrameForHinting(frameSize, presentationTime, 00808 sampleNumberOfFrameStart); 00809 } 00810 } 00811 }
| void SubsessionIOState::useFrameForHinting | ( | unsigned | frameSize, | |
| struct timeval | presentationTime, | |||
| unsigned | startSampleNumber | |||
| ) | [private] |
Definition at line 813 of file QuickTimeFileSink.cpp.
References QuickTimeFileSink::addByte(), QuickTimeFileSink::addHalfWord(), QuickTimeFileSink::addWord(), MediaSubsession::codecName(), RTPSource::curPacketMarkerBit(), SubsessionIOState::hinf::dimm, SubsessionIOState::hinf::dmax, SubsessionIOState::hinf::dmed, duration, envir(), fHINF, MediaSubsession::fmtp_indexlength(), MediaSubsession::fmtp_sizelength(), H263plusVideoRTPSource::fNumSpecialHeaders, fOurSink, fOurSubsession, QuickTimeFileSink::fOutFid, H263plusVideoRTPSource::fPacketSizes, fPrevFrameState, fQTBytesPerFrame, fQTSamplesPerFrame, fQTTimeScale, fQTTimeUnitsPerSample, fQTTotNumSamples, H263plusVideoRTPSource::fSpecialHeaderBytes, H263plusVideoRTPSource::fSpecialHeaderBytesLength, fTrackHintedByUs, if(), maxPacketSize, MediaSubsession::mediumName(), NULL, SubsessionIOState::hinf::nump, SubsessionIOState::hinf::pmax, rtpHeader, RTPSource::rtpPayloadFormat(), MediaSubsession::rtpSource(), MediaSubsession::rtpTimestampFrequency(), seqNum, SubsessionIOState::hinf::tpyl, SubsessionIOState::hinf::trpy, and useFrame1().
Referenced by useFrame().
00815 { 00816 // At this point, we have a single, combined frame - not individual packets. 00817 // For the hint track, we need to split the frame back up into separate packets. 00818 // However, for some RTP sources, then we also need to reuse the special 00819 // header bytes that were at the start of each of the RTP packets. 00820 Boolean hack263 = strcmp(fOurSubsession.codecName(), "H263-1998") == 0; 00821 Boolean hackm4a_generic = strcmp(fOurSubsession.mediumName(), "audio") == 0 00822 && strcmp(fOurSubsession.codecName(), "MPEG4-GENERIC") == 0; 00823 Boolean hackm4a_latm = strcmp(fOurSubsession.mediumName(), "audio") == 0 00824 && strcmp(fOurSubsession.codecName(), "MP4A-LATM") == 0; 00825 Boolean hackm4a = hackm4a_generic || hackm4a_latm; 00826 Boolean haveSpecialHeaders = (hack263 || hackm4a_generic); 00827 00828 // If there has been a previous frame, then output a 'hint sample' for it. 00829 // (We use the current frame's presentation time to compute the previous 00830 // hint sample's duration.) 00831 RTPSource* const rs = fOurSubsession.rtpSource(); // abbrev 00832 struct timeval const& ppt = fPrevFrameState.presentationTime; //abbrev 00833 if (ppt.tv_sec != 0 || ppt.tv_usec != 0) { 00834 double duration = (