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

📄 file_mp4_recorder.cpp

📁 MPEG4音频视频压缩编码(含G.711/ACC/H.261等)
💻 CPP
📖 第 1 页 / 共 3 页
字号:
void CMp4Recorder::ProcessEncodedTextFrame (CMediaFrame *pFrame){  if (m_textFrameNumber == 1) {    if (m_prevTextFrame != NULL) {      if (m_prevTextFrame->RemoveReference()) {	delete m_prevTextFrame;      }    }    m_prevTextFrame = pFrame;    if (m_canRecordVideo == false) return;    if (m_recordAudio) {    // we can record.  Set the timestamp of this frame to the audio start timestamp      m_prevTextFrame->SetTimestamp(m_audioStartTimestamp);      m_textStartTimestamp = m_audioStartTimestamp;    } else {      // need to work with video here, as well...      m_textStartTimestamp = m_prevTextFrame->GetTimestamp();    }    m_textFrameNumber++;    m_textDurationTimescale = 0;    return;  }  Duration textDurationInTicks;  textDurationInTicks = pFrame->GetTimestamp() - m_textStartTimestamp;    Duration textDurationInTimescaleTotal;  textDurationInTimescaleTotal =     GetTimescaleFromTicks(textDurationInTicks, m_textTimeScale);  Duration textDurationInTimescaleFrame;  textDurationInTimescaleFrame =     textDurationInTimescaleTotal - m_textDurationTimescale;  m_textDurationTimescale += textDurationInTimescaleFrame;  MP4WriteSample(m_mp4File, m_textTrackId,		 (uint8_t *)m_prevTextFrame->GetData(),		 m_prevTextFrame->GetDataLength(),		 textDurationInTimescaleFrame);  debug_message("wrote text frame %u", m_textFrameNumber);  m_textFrameNumber++;  if (m_prevTextFrame->RemoveReference()) {    delete m_prevTextFrame;  }  m_prevTextFrame = pFrame;}void CMp4Recorder::DoWriteFrame(CMediaFrame* pFrame){  // dispose of degenerate cases  if (pFrame == NULL) return;  if (!m_sink) {    if (pFrame->RemoveReference()) {      delete pFrame;    }    return;  }  // RAW AUDIO  if (m_stream == NULL &&       pFrame->GetType() == PCMAUDIOFRAME && m_recordAudio) {    if (m_audioFrameNumber == 1) {      debug_message("First raw audio frame at "U64, pFrame->GetTimestamp());      m_audioStartTimestamp = pFrame->GetTimestamp();      m_canRecordVideo = true;      m_prevAudioFrame = pFrame;      m_audioFrameNumber++;      m_audioSamples = 0;      return; // wait until the next audio frame    }#if 0    Duration audioFrameSamples =       m_prevAudioFrame->GetDatalength() /      (m_pConfig->GetIntegerValue(CONFIG_AUDIO_CHANNELS) * sizeof(int16_t));    m_audioSamples += ======#endif    Duration audioDurationInTicks =       pFrame->GetTimestamp() - m_prevAudioFrame->GetTimestamp();    MP4Duration audioDurationInSamples =      MP4ConvertToTrackDuration(m_mp4File, m_audioTrackId,                                audioDurationInTicks, TimestampTicks);#if 0    debug_message("prev "U64" this "U64" diff samples"U64,		  m_prevAudioFrame->GetTimestamp(),		  pFrame->GetTimestamp(),		  audioDurationInSamples);#endif		      m_prevAudioFrame->SetDuration(audioDurationInSamples);    void *pcm;#ifdef WORDS_BIGENDIAN    pcm = m_prevAudioFrame->GetData();#else    uint32_t convert_size = m_prevAudioFrame->GetDataLength();    uint16_t *pdata = (uint16_t *)m_prevAudioFrame->GetData();    if (m_convert_pcm_size < convert_size) {      m_convert_pcm = (uint16_t *)realloc(m_convert_pcm, convert_size);      m_convert_pcm_size = convert_size;    }    convert_size /= sizeof(uint16_t);    for (uint32_t ix = 0; ix < convert_size; ix++) {      uint16_t swap = *pdata++;      m_convert_pcm[ix] = B2N_16(swap);    }    pcm = m_convert_pcm;#endif    MP4WriteSample(                   m_mp4File,                   m_audioTrackId,                   (u_int8_t*)pcm,                   m_prevAudioFrame->GetDataLength(),		   audioDurationInSamples);    //                   m_prevAudioFrame->ConvertDuration(m_audioTimeScale));    m_audioFrameNumber++;    if (m_prevAudioFrame->RemoveReference()) {      delete m_prevAudioFrame;    }    m_prevAudioFrame = pFrame;    // ENCODED AUDIO  } else if (pFrame->GetType() == m_audioFrameType && m_recordAudio) {    ProcessEncodedAudioFrame(pFrame);    // RAW VIDEO  } else if (m_stream == NULL && 	     pFrame->GetType() == YUVVIDEOFRAME && m_recordVideo) {    // we drop raw video frames until we get the first raw audio frame    // after that:    // if we are also recording encoded video, we wait until the first I frame    // else    // we wait until the next raw video frame    // in both cases, the duration of the first raw video frame is stretched    // to the start of the first raw audio frame        if (m_videoFrameNumber == 1) {      // wait until the first raw audio frame is received      if (!m_canRecordVideo) {        if (pFrame->RemoveReference()) delete pFrame;        return;      }      // make sure this frame was captured after the first audio frame      if (m_recordAudio &&	  pFrame->GetTimestamp() < m_audioStartTimestamp) {        if (pFrame->RemoveReference()) delete pFrame;        return;      }      debug_message("First raw video frame at "U64, pFrame->GetTimestamp());      m_videoStartTimestamp = pFrame->GetTimestamp();      m_prevVideoFrame = pFrame;      m_videoFrameNumber++;      return; // wait until the next video frame    }    Duration videoDurationInTicks;        // the first raw video frame is stretched to the begining    // of the first raw audio frame    if (m_videoFrameNumber == 2 && m_recordAudio) {      videoDurationInTicks =        pFrame->GetTimestamp() - m_audioStartTimestamp;    } else {      videoDurationInTicks =        pFrame->GetTimestamp() - m_prevVideoFrame->GetTimestamp();    }    m_prevVideoFrame->SetDuration(videoDurationInTicks);    yuv_media_frame_t *pYUV = (yuv_media_frame_t *)m_prevVideoFrame->GetData();    if (pYUV->y + m_pConfig->m_ySize == pYUV->u) {      MP4WriteSample(		     m_mp4File,		     m_videoTrackId,		     pYUV->y,		     m_pConfig->m_yuvSize,		     m_prevVideoFrame->ConvertDuration(m_videoTimeScale));    } else {      if (m_rawYUV == NULL) {	debug_message("Mallocing %u", m_pConfig->m_yuvSize);	m_rawYUV = (uint8_t *)malloc(m_pConfig->m_yuvSize);      }      CopyYuv(pYUV->y, pYUV->u, pYUV->v,	      pYUV->y_stride, pYUV->uv_stride, pYUV->uv_stride,	      m_rawYUV, 	      m_rawYUV + m_pConfig->m_ySize, 	      m_rawYUV + m_pConfig->m_ySize + m_pConfig->m_uvSize,	      m_pConfig->m_videoWidth, 	      m_pConfig->m_videoWidth / 2, 	      m_pConfig->m_videoWidth / 2,	      m_pConfig->m_videoWidth, m_pConfig->m_videoHeight);      MP4WriteSample(m_mp4File, 		     m_videoTrackId, 		     m_rawYUV,		     m_pConfig->m_yuvSize,		     m_prevVideoFrame->ConvertDuration(m_videoTimeScale));    }	          m_videoFrameNumber++;    if (m_prevVideoFrame->RemoveReference()) {      delete m_prevVideoFrame;    }    m_prevVideoFrame = pFrame;    // ENCODED VIDEO  } else if (pFrame->GetType() == m_videoFrameType && m_recordVideo) {    ProcessEncodedVideoFrame(pFrame);  } else if (pFrame->GetType() == m_textFrameType && m_recordText) {    ProcessEncodedTextFrame(pFrame);  } else {    // degenerate case    if (pFrame->RemoveReference()) delete pFrame;  }}void CMp4Recorder::DoStopRecord(){  if (!m_sink) return;  Duration totalAudioDuration = 0;  // write last audio frame  if (m_prevAudioFrame) {    MP4WriteSample(                   m_mp4File,                   m_audioTrackId,                   (u_int8_t*)m_prevAudioFrame->GetData(),                    m_prevAudioFrame->GetDataLength(),                   m_prevAudioFrame->ConvertDuration(m_audioTimeScale));    m_audioSamples += m_prevAudioFrame->GetDuration();    totalAudioDuration = m_audioSamples;    totalAudioDuration *= TimestampTicks;    totalAudioDuration /= m_audioTimeScale;    if (m_prevAudioFrame->RemoveReference()) {      delete m_prevAudioFrame;    }    if (m_audioFrameType == AMRNBAUDIOFRAME ||	m_audioFrameType == AMRWBAUDIOFRAME) {      MP4SetAmrModeSet(m_mp4File, m_audioTrackId, m_amrMode);    }  }   // write last video frame  if (m_prevVideoFrame) {    if (m_stream == NULL) {#if 1      error_message("write last raw video frame");#else      MP4WriteSample(		     m_mp4File,		     m_videoTrackId,		     (u_int8_t*)m_prevVideoFrame->GetData(), 		     m_prevVideoFrame->GetDataLength(),		     m_prevVideoFrame->ConvertDuration(m_videoTimeScale));#endif      if (m_prevVideoFrame->RemoveReference()) {	delete m_prevVideoFrame;      }      CHECK_AND_FREE(m_rawYUV);    } else {      bool isIFrame;      Duration rend_offset = 0;      if (m_prevVideoFrame->GetType() == H264VIDEOFRAME) {	WriteH264Frame(m_prevVideoFrame, 		       m_prevVideoFrame->ConvertDuration(m_videoTimeScale));      } else {	if (m_prevVideoFrame->GetType() == MPEG4VIDEOFRAME ||	    m_prevVideoFrame->GetType() == H263VIDEOFRAME) {	  isIFrame = 	    (MP4AV_Mpeg4GetVopType(				   (u_int8_t*) m_prevVideoFrame->GetData(),				   m_prevVideoFrame->GetDataLength()) == VOP_TYPE_I);	} else {	  int ret, ftype;	  ret = 	    MP4AV_Mpeg3FindPictHdr((u_int8_t *)m_prevVideoFrame->GetData(), 				   m_prevVideoFrame->GetDataLength(),				   &ftype);	  isIFrame = false;	  if (ret >= 0) {	    if (ftype == 1) isIFrame = true;	    if (ftype != 3) {	      rend_offset = m_prevVideoFrame->GetPtsTimestamp() - 		m_prevVideoFrame->GetTimestamp();	      rend_offset = GetTimescaleFromTicks(rend_offset, m_movieTimeScale);	    }	  }	}	MP4WriteSample(		       m_mp4File,		       m_videoTrackId,		       (u_int8_t*) m_prevVideoFrame->GetData(),		       m_prevVideoFrame->GetDataLength(),		       m_prevVideoFrame->ConvertDuration(m_videoTimeScale),		       rend_offset,		       isIFrame);      }      if (m_prevVideoFrame->RemoveReference()) {	delete m_prevVideoFrame;      }    }  }  if (m_prevTextFrame) {    Duration lastDuration = TimestampTicks;    if (totalAudioDuration != 0) {      Duration totalSoFar = m_prevTextFrame->GetTimestamp() - m_textStartTimestamp;      if (totalAudioDuration > totalSoFar) {	lastDuration = totalAudioDuration - totalSoFar;      }    }    debug_message("last duration "U64" timescale "U64,		  lastDuration, GetTimescaleFromTicks(lastDuration, m_textTimeScale));    MP4WriteSample(m_mp4File, 		   m_textTrackId, 		   (uint8_t *)m_prevTextFrame->GetData(),		   m_prevTextFrame->GetDataLength(),		   GetTimescaleFromTicks(lastDuration, m_textTimeScale));    if (m_prevTextFrame->RemoveReference()) {      delete m_prevTextFrame;    }    m_prevTextFrame = NULL;  }      CHECK_AND_FREE(m_videoH264Seq);  m_videoH264SeqSize = 0;  CHECK_AND_FREE(m_videoH264Pic);  m_videoH264PicSize = 0;  // close the mp4 file  MP4Close(m_mp4File);  m_mp4File = NULL;      debug_message("done with writing last frame");  bool optimize = false;  // create hint tracks  if (m_pConfig->GetBoolValue(CONFIG_RECORD_MP4_HINT_TRACKS)) {    m_mp4File = MP4Modify(m_mp4FileName, MP4_DETAILS_ERROR);    if (m_pConfig->GetBoolValue(CONFIG_RECORD_MP4_OPTIMIZE)) {      optimize = true;    }    if (m_stream != NULL) {      if (MP4_IS_VALID_TRACK_ID(m_videoTrackId) && m_stream) {	create_mp4_video_hint_track(m_video_profile,				    m_mp4File, 				    m_videoTrackId,				    m_pConfig->GetIntegerValue(CONFIG_RTP_PAYLOAD_SIZE));      }      if (MP4_IS_VALID_TRACK_ID(m_audioTrackId)) {	create_mp4_audio_hint_track(m_audio_profile, 				    m_mp4File, 				    m_audioTrackId,				    m_pConfig->GetIntegerValue(CONFIG_RTP_PAYLOAD_SIZE));      }      if (MP4_IS_VALID_TRACK_ID(m_textTrackId)) {	create_mp4_text_hint_track(m_text_profile, 				   m_mp4File, 				   m_textTrackId,				   m_pConfig->GetIntegerValue(CONFIG_RTP_PAYLOAD_SIZE));      }    } else {      if (MP4_IS_VALID_TRACK_ID(m_audioTrackId)) {	L16Hinter(m_mp4File, 		  m_audioTrackId,		  m_pConfig->GetIntegerValue(CONFIG_RTP_PAYLOAD_SIZE));      }    }    MP4Close(m_mp4File);    m_mp4File = NULL;  }  debug_message("done with hint");  // add ISMA style OD and Scene tracks  if (m_stream != NULL) {    bool useIsmaTag = false;    // if AAC track is present, can tag this as ISMA compliant content    useIsmaTag = m_makeIsmaCompliant;    if (m_makeIod) {      MP4MakeIsmaCompliant(			   m_mp4FileName,                           0,                           useIsmaTag);    }  }  if (optimize) {    MP4Optimize(m_mp4FileName);  }  m_sink = false;}

⌨️ 快捷键说明

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