📄 quicktimefilesink.cpp
字号:
if (outOfSync > syncThreshold) { // The track's data is too short, so end this edit, add a new // 'empty' edit after it, and start a new edit // (at the current track posn.): if (trackDurationOfEdit > 0.0) addEdit(trackDurationOfEdit); addEmptyEdit(outOfSync); editStartTime = chunkStartTime; editTrackPosition = currentTrackPosition; } else if (outOfSync < -syncThreshold) { // The track's data is too long, so end this edit, and start // a new edit (pointing at the current track posn.): if (movieDurationOfEdit > 0.0) addEdit(movieDurationOfEdit); editStartTime = chunkStartTime; editTrackPosition = currentTrackPosition; } // Note the duration of this chunk: unsigned numChannels = fCurrentIOState->fOurSubsession.numChannels(); chunkDuration = chunk->fNumFrames*chunk->fFrameDuration/numChannels; currentTrackPosition += chunkDuration; chunk = chunk->fNextChunk; } // Write out the final edit trackDurationOfEdit += (double)chunkDuration/fCurrentIOState->fQTTimeScale; if (trackDurationOfEdit > 0.0) addEdit(trackDurationOfEdit); // Now go back and fill in the "Number of entries" field: setWord(numEntriesPosition, numEdits); // Also, if the sum of all of the edit durations exceeds the // track duration that we already computed (from sample durations), // then reset the track duration to this new value: if (totalDurationOfEdits > fCurrentIOState->fQTDurationM) { fCurrentIOState->fQTDurationM = totalDurationOfEdits; setWord(fCurrentIOState->fTKHD_durationPosn, totalDurationOfEdits); // Also, check whether the overall movie duration needs to change: if (totalDurationOfEdits > fMaxTrackDurationM) { fMaxTrackDurationM = totalDurationOfEdits; setWord(fMVHD_durationPosn, totalDurationOfEdits); } // Also, convert to track time scale: double scaleFactor = fCurrentIOState->fQTTimeScale/(double)movieTimeScale(); fCurrentIOState->fQTDurationT = (unsigned)(totalDurationOfEdits*scaleFactor); }addAtomEnd;addAtom(tref); size += addAtom_hint();addAtomEnd;addAtom(hint); SubsessionIOState* hintedTrack = fCurrentIOState->fTrackHintedByUs; // Assert: hintedTrack != NULL size += addWord(hintedTrack->fTrackID);addAtomEnd;addAtom(mdia); size += addAtom_mdhd(); size += addAtom_hdlr(); size += addAtom_minf();addAtomEnd;addAtom(mdhd); size += addWord(0x00000000); // Version + Flags size += addWord(fAppleCreationTime); // Creation time size += addWord(fAppleCreationTime); // Modification time unsigned const timeScale = fCurrentIOState->fQTTimeScale; size += addWord(timeScale); // Time scale unsigned const duration = fCurrentIOState->fQTDurationT; // track units size += addWord(duration); // Duration size += addWord(0x00000000); // Language+QualityaddAtomEnd;addAtom(hdlr); size += addWord(0x00000000); // Version + Flags size += add4ByteString("mhlr"); // Component type size += addWord(fCurrentIOState->fQTcomponentSubtype); // Component subtype size += add4ByteString("appl"); // Component manufacturer size += addWord(0x00000000); // Component flags size += addWord(0x00000000); // Component flags mask size += addArbitraryString(fCurrentIOState->fQTcomponentName); // Component nameaddAtomEnd;addAtom(minf); SubsessionIOState::atomCreationFunc mediaInformationAtomCreator = fCurrentIOState->fQTMediaInformationAtomCreator; size += (this->*mediaInformationAtomCreator)(); size += addAtom_hdlr2(); size += addAtom_dinf(); size += addAtom_stbl();addAtomEnd;addAtom(smhd); size += addZeroWords(2); // Version+Flags+Balance+ReservedaddAtomEnd;addAtom(vmhd); size += addWord(0x00000001); // Version + Flags size += addWord(0x00408000); // Graphics mode + Opcolor[red] size += addWord(0x80008000); // Opcolor[green} + Opcolor[blue]addAtomEnd;addAtom(gmhd); size += addAtom_gmin();addAtomEnd;addAtom(gmin); size += addWord(0x00000000); // Version + Flags // The following fields probably aren't used for hint tracks, so just // use values that I've seen in other files: size += addWord(0x00408000); // Graphics mode + Opcolor (1st 2 bytes) size += addWord(0x80008000); // Opcolor (last 4 bytes) size += addWord(0x00000000); // Balance + ReservedaddAtomEnd;unsigned QuickTimeFileSink::addAtom_hdlr2() { int64_t initFilePosn = TellFile64(fOutFid); unsigned size = addAtomHeader("hdlr"); size += addWord(0x00000000); // Version + Flags size += add4ByteString("dhlr"); // Component type size += add4ByteString("alis"); // Component subtype size += add4ByteString("appl"); // Component manufacturer size += addZeroWords(2); // Component flags+Component flags mask size += addArbitraryString("Apple Alias Data Handler"); // Component nameaddAtomEnd;addAtom(dinf); size += addAtom_dref();addAtomEnd;addAtom(dref); size += addWord(0x00000000); // Version + Flags size += addWord(0x00000001); // Number of entries size += addAtom_alis();addAtomEnd;addAtom(alis); size += addWord(0x00000001); // Version + FlagsaddAtomEnd;addAtom(stbl); size += addAtom_stsd(); size += addAtom_stts(); if (fCurrentIOState->fQTcomponentSubtype == fourChar('v','i','d','e')) { size += addAtom_stss(); // only for video streams } size += addAtom_stsc(); size += addAtom_stsz(); size += addAtom_co64();addAtomEnd;addAtom(stsd); size += addWord(0x00000000); // Version+Flags size += addWord(0x00000001); // Number of entries SubsessionIOState::atomCreationFunc mediaDataAtomCreator = fCurrentIOState->fQTMediaDataAtomCreator; size += (this->*mediaDataAtomCreator)();addAtomEnd;unsigned QuickTimeFileSink::addAtom_genericMedia() { int64_t initFilePosn = TellFile64(fOutFid); // Our source is assumed to be a "QuickTimeGenericRTPSource" // Use its "sdAtom" state for our contents: QuickTimeGenericRTPSource* rtpSource = (QuickTimeGenericRTPSource*) fCurrentIOState->fOurSubsession.rtpSource(); QuickTimeGenericRTPSource::QTState& qtState = rtpSource->qtState; char const* from = qtState.sdAtom; unsigned size = qtState.sdAtomSize; for (unsigned i = 0; i < size; ++i) addByte(from[i]);addAtomEnd;unsigned QuickTimeFileSink::addAtom_soundMediaGeneral() { int64_t initFilePosn = TellFile64(fOutFid); unsigned size = addAtomHeader(fCurrentIOState->fQTAudioDataType);// General sample description fields: size += addWord(0x00000000); // Reserved size += addWord(0x00000001); // Reserved+Data reference index// Sound sample description fields: unsigned short const version = fCurrentIOState->fQTSoundSampleVersion; size += addWord(version<<16); // Version+Revision level size += addWord(0x00000000); // Vendor unsigned short numChannels = (unsigned short)(fCurrentIOState->fOurSubsession.numChannels()); size += addHalfWord(numChannels); // Number of channels size += addHalfWord(0x0010); // Sample size // size += addWord(0x00000000); // Compression ID+Packet size size += addWord(0xfffe0000); // Compression ID+Packet size ##### unsigned const sampleRateFixedPoint = fCurrentIOState->fQTTimeScale << 16; size += addWord(sampleRateFixedPoint); // Sample rateaddAtomEnd;unsigned QuickTimeFileSink::addAtom_Qclp() { // The beginning of this atom looks just like a general Sound Media atom, // except with a version field of 1: int64_t initFilePosn = TellFile64(fOutFid); fCurrentIOState->fQTAudioDataType = "Qclp"; fCurrentIOState->fQTSoundSampleVersion = 1; unsigned size = addAtom_soundMediaGeneral(); // Next, add the four fields that are particular to version 1: // (Later, parameterize these #####) size += addWord(0x000000a0); // samples per packet size += addWord(0x00000000); // ??? size += addWord(0x00000000); // ??? size += addWord(0x00000002); // bytes per sample (uncompressed) // Other special fields are in a 'wave' atom that follows: size += addAtom_wave();addAtomEnd;addAtom(wave); size += addAtom_frma(); if (strcmp(fCurrentIOState->fQTAudioDataType, "Qclp") == 0) { size += addWord(0x00000014); // ??? size += add4ByteString("Qclp"); // ??? if (fCurrentIOState->fQTBytesPerFrame == 35) { size += addAtom_Fclp(); // full-rate QCELP } else { size += addAtom_Hclp(); // half-rate QCELP } // what about other QCELP 'rates'??? ##### size += addWord(0x00000008); // ??? size += addWord(0x00000000); // ??? size += addWord(0x00000000); // ??? size += addWord(0x00000008); // ??? } else if (strcmp(fCurrentIOState->fQTAudioDataType, "mp4a") == 0) { size += addWord(0x0000000c); // ??? size += add4ByteString("mp4a"); // ??? size += addWord(0x00000000); // ??? size += addAtom_esds(); // ESDescriptor size += addWord(0x00000008); // ??? size += addWord(0x00000000); // ??? }addAtomEnd;addAtom(frma); size += add4ByteString(fCurrentIOState->fQTAudioDataType); // ???addAtomEnd;addAtom(Fclp); size += addWord(0x00000000); // ???addAtomEnd;addAtom(Hclp); size += addWord(0x00000000); // ???addAtomEnd;unsigned QuickTimeFileSink::addAtom_mp4a() { unsigned size = 0; // The beginning of this atom looks just like a general Sound Media atom, // except with a version field of 1: int64_t initFilePosn = TellFile64(fOutFid); fCurrentIOState->fQTAudioDataType = "mp4a"; if (fGenerateMP4Format) { fCurrentIOState->fQTSoundSampleVersion = 0; size = addAtom_soundMediaGeneral(); size += addAtom_esds(); } else { fCurrentIOState->fQTSoundSampleVersion = 1; size = addAtom_soundMediaGeneral(); // Next, add the four fields that are particular to version 1: // (Later, parameterize these #####) size += addWord(fCurrentIOState->fQTTimeUnitsPerSample); size += addWord(0x00000001); // ??? size += addWord(0x00000001); // ??? size += addWord(0x00000002); // bytes per sample (uncompressed) // Other special fields are in a 'wave' atom that follows: size += addAtom_wave(); }addAtomEnd;addAtom(esds); //##### MediaSubsession& subsession = fCurrentIOState->fOurSubsession; if (strcmp(subsession.mediumName(), "audio") == 0) { // MPEG-4 audio size += addWord(0x00000000); // ??? size += addWord(0x03808080); // ??? size += addWord(0x2a000000); // ??? size += addWord(0x04808080); // ??? size += addWord(0x1c401500); // ??? size += addWord(0x18000000); // ??? size += addWord(0x6d600000); // ??? size += addWord(0x6d600580); // ??? size += addByte(0x80); size += addByte(0x80); // ??? } else if (strcmp(subsession.mediumName(), "video") == 0) { // MPEG-4 video size += addWord(0x00000000); // ??? size += addWord(0x03370000); // ??? size += addWord(0x1f042f20); // ??? size += addWord(0x1104fd46); // ??? size += addWord(0x000d4e10); // ??? size += addWord(0x000d4e10); // ??? size += addByte(0x05); // ??? } // Add the source's 'config' information: unsigned configSize; unsigned char* config = parseGeneralConfigStr(subsession.fmtp_config(), configSize); size += addByte(configSize); for (unsigned i = 0; i < configSize; ++i) { size += addByte(config[i]); } delete[] config; if (strcmp(subsession.mediumName(), "audio") == 0) { // MPEG-4 audio size += addWord(0x06808080); // ??? size += addHalfWord(0x0102); // ??? } else { // MPEG-4 video size += addHalfWord(0x0601); // ??? size += addByte(0x02); // ??? } //#####addAtomEnd;addAtom(srcq); //##### size += addWord(0x00000040); // ??? //#####addAtomEnd;addAtom(h263);// General sample description fields: size += addWord(0x00000000); // Reserved size += addWord(0x00000001); // Reserved+Data reference index// Video sample description fields: size += addWord(0x00020001); // Version+Revision level size += add4ByteString("appl"); // Vendor size += addWord(0x00000000); // Temporal quality size += addWord(0x000002fc); // Spatial quality unsigned const widthAndHeight = (fMovieWidth<<16)|fMovieHeight; size += addWord(widthAndHeight); // Width+height size += addWord(0x00480000); // Horizontal resolution size += addWord(0x00480000); // Vertical resolution size += addWord(0x00000000); // Data size size += addWord(0x00010548); // Frame count+Compressor name (start) // "H.263" size += addWord(0x2e323633); // Compressor name (continued) size += addZeroWords(6); // Compressor name (continued - zero) size += addWord(0x00000018); // Compressor name (final)+Depth size += addHalfWord(0xffff); // Color table idaddAtomEnd;addAtom(avc1);// General sample description fields:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -