⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avifilesink.cpp

📁 流媒体传输协议的实现代码,非常有用.可以支持rtsp mms等流媒体传输协议
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    } else if (strcmp(fOurSubsession.codecName(), "H263-1998") == 0 ||	       strcmp(fOurSubsession.codecName(), "H263-2000") == 0) {      fAVICodecHandlerType = fourChar('H','2','6','3');    } else if (strcmp(fOurSubsession.codecName(), "H264") == 0) {      fAVICodecHandlerType = fourChar('H','2','6','4');    } else {      fAVICodecHandlerType = fourChar('?','?','?','?');    }    fAVIScale = 1; // ??? #####    fAVIRate = fOurSink.fMovieFPS; // ??? #####    fAVISize = fOurSink.fMovieWidth*fOurSink.fMovieHeight*3; // ??? #####  } else if (fIsAudio) {    fIsByteSwappedAudio = False; // by default    fAVISubsessionTag      = fourChar('0'+subsessionIndex/10,'0'+subsessionIndex%10,'w','b');    fAVICodecHandlerType = 1; // ??? ####    unsigned numChannels = fOurSubsession.numChannels();    fAVISamplingFrequency = fOurSubsession.rtpTimestampFrequency(); // default    if (strcmp(fOurSubsession.codecName(), "L16") == 0) {      fIsByteSwappedAudio = True; // need to byte-swap data before writing it      fWAVCodecTag = 0x0001;      fAVIScale = fAVISize = 2*numChannels; // 2 bytes/sample      fAVIRate = fAVISize*fAVISamplingFrequency;    } else if (strcmp(fOurSubsession.codecName(), "L8") == 0) {      fWAVCodecTag = 0x0001;      fAVIScale = fAVISize = numChannels; // 1 byte/sample      fAVIRate = fAVISize*fAVISamplingFrequency;    } else if (strcmp(fOurSubsession.codecName(), "PCMA") == 0) {      fWAVCodecTag = 0x0006;      fAVIScale = fAVISize = numChannels; // 1 byte/sample      fAVIRate = fAVISize*fAVISamplingFrequency;    } else if (strcmp(fOurSubsession.codecName(), "PCMU") == 0) {      fWAVCodecTag = 0x0007;      fAVIScale = fAVISize = numChannels; // 1 byte/sample      fAVIRate = fAVISize*fAVISamplingFrequency;    } else if (strcmp(fOurSubsession.codecName(), "MPA") == 0) {      fWAVCodecTag = 0x0050;      fAVIScale = fAVISize = 1;      fAVIRate = 0; // ??? #####    } else {      fWAVCodecTag = 0x0001; // ??? #####      fAVIScale = fAVISize = 1;      fAVIRate = 0; // ??? #####    }  } else { // unknown medium    fAVISubsessionTag      = fourChar('0'+subsessionIndex/10,'0'+subsessionIndex%10,'?','?');    fAVICodecHandlerType = 0;    fAVIScale = fAVISize = 1;    fAVIRate = 0; // ??? #####  }}void AVISubsessionIOState::afterGettingFrame(unsigned packetDataSize,					  struct timeval presentationTime) {  // Begin by checking whether there was a gap in the RTP stream.  // If so, try to compensate for this (if desired):  unsigned short rtpSeqNum    = fOurSubsession.rtpSource()->curPacketRTPSeqNum();  if (fOurSink.fPacketLossCompensate && fPrevBuffer->bytesInUse() > 0) {    short seqNumGap = rtpSeqNum - fLastPacketRTPSeqNum;    for (short i = 1; i < seqNumGap; ++i) {      // Insert a copy of the previous frame, to compensate for the loss:      useFrame(*fPrevBuffer);    }  }  fLastPacketRTPSeqNum = rtpSeqNum;  // Now, continue working with the frame that we just got  if (fBuffer->bytesInUse() == 0) {    fBuffer->setPresentationTime(presentationTime);  }  fBuffer->addBytes(packetDataSize);  useFrame(*fBuffer);  if (fOurSink.fPacketLossCompensate) {    // Save this frame, in case we need it for recovery:    SubsessionBuffer* tmp = fPrevBuffer; // assert: != NULL    fPrevBuffer = fBuffer;    fBuffer = tmp;  }  fBuffer->reset(); // for the next input  // Now, try getting more frames:  fOurSink.continuePlaying();}void AVISubsessionIOState::useFrame(SubsessionBuffer& buffer) {  unsigned char* const frameSource = buffer.dataStart();  unsigned const frameSize = buffer.bytesInUse();  struct timeval const& presentationTime = buffer.presentationTime();  if (fPrevPresentationTime.tv_usec != 0||fPrevPresentationTime.tv_sec != 0) {    int uSecondsDiff      = (presentationTime.tv_sec - fPrevPresentationTime.tv_sec)*1000000      + (presentationTime.tv_usec - fPrevPresentationTime.tv_usec);    if (uSecondsDiff > 0) {      unsigned bytesPerSecond = (unsigned)((frameSize*1000000.0)/uSecondsDiff);      if (bytesPerSecond > fMaxBytesPerSecond) {	fMaxBytesPerSecond = bytesPerSecond;      }    }  }  fPrevPresentationTime = presentationTime;  if (fIsByteSwappedAudio) {    // We need to swap the 16-bit audio samples from big-endian    // to little-endian order, before writing them to a file:    for (unsigned i = 0; i < frameSize; i += 2) {      unsigned char tmp = frameSource[i];      frameSource[i] = frameSource[i+1];      frameSource[i+1] = tmp;    }  }  // Write the data into the file:  fOurSink.fNumBytesWritten += fOurSink.addWord(fAVISubsessionTag);   fOurSink.fNumBytesWritten += fOurSink.addWord(frameSize);  fwrite(frameSource, 1, frameSize, fOurSink.fOutFid);  fOurSink.fNumBytesWritten += frameSize;  // Pad to an even length:  if (frameSize%2 != 0) fOurSink.fNumBytesWritten += fOurSink.addByte(0);  ++fNumFrames;}void AVISubsessionIOState::onSourceClosure() {  fOurSourceIsActive = False;  fOurSink.onSourceClosure1();}////////// AVI-specific implementation //////////unsigned AVIFileSink::addWord(unsigned word) {  // Add "word" to the file in little-endian order:  addByte(word); addByte(word>>8);  addByte(word>>16); addByte(word>>24);  return 4;}unsigned AVIFileSink::addHalfWord(unsigned short halfWord) {  // Add "halfWord" to the file in little-endian order:  addByte((unsigned char)halfWord); addByte((unsigned char)(halfWord>>8));  return 2;}unsigned AVIFileSink::addZeroWords(unsigned numWords) {  for (unsigned i = 0; i < numWords; ++i) {    addWord(0);  }  return numWords*4;}unsigned AVIFileSink::add4ByteString(char const* str) {  addByte(str[0]); addByte(str[1]); addByte(str[2]);  addByte(str[3] == '\0' ? ' ' : str[3]); // e.g., for "AVI "  return 4;}void AVIFileSink::setWord(unsigned filePosn, unsigned size) {  do {    if (fseek(fOutFid, filePosn, SEEK_SET) < 0) break;    addWord(size);    if (fseek(fOutFid, 0, SEEK_END) < 0) break; // go back to where we were    return;  } while (0);  // One of the fseek()s failed, probable because we're not a seekable file  envir() << "AVIFileSink::setWord(): fseek failed (err "	  << envir().getErrno() << ")\n";}// Methods for writing particular file headers.  Note the following macros:#define addFileHeader(tag,name) \    unsigned AVIFileSink::addFileHeader_##name() { \        add4ByteString("" #tag ""); \        unsigned headerSizePosn = ftell(fOutFid); addWord(0); \        add4ByteString("" #name ""); \        unsigned ignoredSize = 8;/*don't include size of tag or size fields*/ \        unsigned size = 12#define addFileHeader1(name) \    unsigned AVIFileSink::addFileHeader_##name() { \        add4ByteString("" #name ""); \        unsigned headerSizePosn = ftell(fOutFid); addWord(0); \        unsigned ignoredSize = 8;/*don't include size of name or size fields*/ \        unsigned size = 8#define addFileHeaderEnd \  setWord(headerSizePosn, size-ignoredSize); \  return size; \}addFileHeader(RIFF,AVI);    size += addFileHeader_hdrl();    size += addFileHeader_movi();     fRIFFSizePosition = headerSizePosn;    fRIFFSizeValue = size-ignoredSize;addFileHeaderEnd;addFileHeader(LIST,hdrl);    size += addFileHeader_avih();    // Then, add a "strl" header for each subsession (stream):    // (Make the video subsession (if any) come before the audio subsession.)    unsigned subsessionCount = 0;    MediaSubsessionIterator iter(fInputSession);    MediaSubsession* subsession;    while ((subsession = iter.next()) != NULL) {      fCurrentIOState = (AVISubsessionIOState*)(subsession->miscPtr);      if (fCurrentIOState == NULL) continue;      if (strcmp(subsession->mediumName(), "video") != 0) continue;      fCurrentIOState->setAVIstate(subsessionCount++);      size += addFileHeader_strl();    }    iter.reset();    while ((subsession = iter.next()) != NULL) {      fCurrentIOState = (AVISubsessionIOState*)(subsession->miscPtr);      if (fCurrentIOState == NULL) continue;      if (strcmp(subsession->mediumName(), "video") == 0) continue;      fCurrentIOState->setAVIstate(subsessionCount++);      size += addFileHeader_strl();    }    // Then add another JUNK entry    ++fJunkNumber;    size += addFileHeader_JUNK(); addFileHeaderEnd;#define AVIF_HASINDEX           0x00000010 // Index at end of file?#define AVIF_MUSTUSEINDEX       0x00000020#define AVIF_ISINTERLEAVED      0x00000100#define AVIF_TRUSTCKTYPE        0x00000800 // Use CKType to find key frames?#define AVIF_WASCAPTUREFILE     0x00010000#define AVIF_COPYRIGHTED        0x00020000addFileHeader1(avih);    unsigned usecPerFrame = fMovieFPS == 0 ? 0 : 1000000/fMovieFPS;    size += addWord(usecPerFrame); // dwMicroSecPerFrame    fAVIHMaxBytesPerSecondPosition = ftell(fOutFid);    size += addWord(0); // dwMaxBytesPerSec (fill in later)    size += addWord(0); // dwPaddingGranularity    size += addWord(AVIF_TRUSTCKTYPE|AVIF_HASINDEX|AVIF_ISINTERLEAVED); // dwFlags    fAVIHFrameCountPosition = ftell(fOutFid);    size += addWord(0); // dwTotalFrames (fill in later)    size += addWord(0); // dwInitialFrame    size += addWord(fNumSubsessions); // dwStreams    size += addWord(fBufferSize); // dwSuggestedBufferSize    size += addWord(fMovieWidth); // dwWidth    size += addWord(fMovieHeight); // dwHeight    size += addZeroWords(4); // dwReservedaddFileHeaderEnd;addFileHeader(LIST,strl);    size += addFileHeader_strh();     size += addFileHeader_strf();     fJunkNumber = 0;    size += addFileHeader_JUNK(); addFileHeaderEnd;addFileHeader1(strh);    size += add4ByteString(fCurrentIOState->fIsVideo ? "vids" :			   fCurrentIOState->fIsAudio ? "auds" :			   "????"); // fccType    size += addWord(fCurrentIOState->fAVICodecHandlerType); // fccHandler    size += addWord(0); // dwFlags    size += addWord(0); // wPriority + wLanguage    size += addWord(0); // dwInitialFrames    size += addWord(fCurrentIOState->fAVIScale); // dwScale    size += addWord(fCurrentIOState->fAVIRate); // dwRate    size += addWord(0); // dwStart    fCurrentIOState->fSTRHFrameCountPosition = ftell(fOutFid);    size += addWord(0); // dwLength (fill in later)    size += addWord(fBufferSize); // dwSuggestedBufferSize    size += addWord((unsigned)-1); // dwQuality    size += addWord(fCurrentIOState->fAVISize); // dwSampleSize    size += addWord(0); // rcFrame (start)    if (fCurrentIOState->fIsVideo) {        size += addHalfWord(fMovieWidth);        size += addHalfWord(fMovieHeight);    } else {        size += addWord(0);    }addFileHeaderEnd;addFileHeader1(strf);    if (fCurrentIOState->fIsVideo) {      // Add a BITMAPINFO header:      unsigned extraDataSize = 0;      size += addWord(10*4 + extraDataSize); // size      size += addWord(fMovieWidth);      size += addWord(fMovieHeight);      size += addHalfWord(1); // planes      size += addHalfWord(24); // bits-per-sample #####      size += addWord(fCurrentIOState->fAVICodecHandlerType); // compr. type      size += addWord(fCurrentIOState->fAVISize);      size += addZeroWords(4); // ??? #####      // Later, add extra data here (if any) #####    } else if (fCurrentIOState->fIsAudio) {      // Add a WAVFORMATEX header:      size += addHalfWord(fCurrentIOState->fWAVCodecTag);      unsigned numChannels = fCurrentIOState->fOurSubsession.numChannels();      size += addHalfWord(numChannels);      size += addWord(fCurrentIOState->fAVISamplingFrequency);      size += addWord(fCurrentIOState->fAVIRate); // bytes per second      size += addHalfWord(fCurrentIOState->fAVISize); // block alignment      unsigned bitsPerSample = (fCurrentIOState->fAVISize*8)/numChannels;      size += addHalfWord(bitsPerSample);      if (strcmp(fCurrentIOState->fOurSubsession.codecName(), "MPA") == 0) {	// Assume MPEG layer II audio (not MP3): #####	size += addHalfWord(22); // wav_extra_size	size += addHalfWord(2); // fwHeadLayer	size += addWord(8*fCurrentIOState->fAVIRate); // dwHeadBitrate #####	size += addHalfWord(numChannels == 2 ? 1: 8); // fwHeadMode	size += addHalfWord(0); // fwHeadModeExt	size += addHalfWord(1); // wHeadEmphasis	size += addHalfWord(16); // fwHeadFlags	size += addWord(0); // dwPTSLow	size += addWord(0); // dwPTSHigh      }    }addFileHeaderEnd;#define AVI_MASTER_INDEX_SIZE   256addFileHeader1(JUNK);    if (fJunkNumber == 0) {      size += addHalfWord(4); // wLongsPerEntry      size += addHalfWord(0); // bIndexSubType + bIndexType      size += addWord(0); // nEntriesInUse #####      size += addWord(fCurrentIOState->fAVISubsessionTag); // dwChunkId      size += addZeroWords(2); // dwReserved      size += addZeroWords(AVI_MASTER_INDEX_SIZE*4);    } else {      size += add4ByteString("odml");      size += add4ByteString("dmlh");      unsigned wtfCount = 248;      size += addWord(wtfCount); // ??? #####      size += addZeroWords(wtfCount/4);    }addFileHeaderEnd;addFileHeader(LIST,movi);    fMoviSizePosition = headerSizePosn;    fMoviSizeValue = size-ignoredSize;addFileHeaderEnd;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -