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

📄 file_mp4_recorder.cpp

📁 完整的RTP RTSP代码库
💻 CPP
📖 第 1 页 / 共 3 页
字号:
      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_recordAudio) {    if ((m_stream == NULL && pFrame->GetType() == PCMAUDIOFRAME) ||	(m_stream != NULL && pFrame->GetType() == NETPCMAUDIOFRAME)) {      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      if (pFrame->GetType() != NETPCMAUDIOFRAME) {	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;      } else {	pcm = m_prevAudioFrame->GetData();      }#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;      return;      // ENCODED AUDIO    } else if (pFrame->GetType() == m_audioFrameType) {      ProcessEncodedAudioFrame(pFrame);      return;      // RAW VIDEO    }   }  if (m_recordVideo) {    if (m_stream == NULL && pFrame->GetType() == YUVVIDEOFRAME) {      // 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;      return;      // ENCODED VIDEO    } else if (pFrame->GetType() == m_videoFrameType) {      ProcessEncodedVideoFrame(pFrame);      return;    }  }  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) {    if (m_pConfig->GetBoolValue(CONFIG_RECORD_MP4_ISMA_COMPLIANT)) {      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 + -