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

📄 media_flow.cpp

📁 MPEG4音频视频压缩编码(含G.711/ACC/H.261等)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
  m_video_profile_list->Load();  if (m_video_profile_list->GetCount() == 0 ||      m_video_profile_list->FindProfile("default") == NULL) {    if (m_video_profile_list->CreateConfig("default") == false) {      error_message("Can't create video default profile");      return false;    } else {      debug_message("Created default video profile");    }  }  snprintf(profile_dir, PATH_MAX, "%s/Audio", base);  if (CheckandCreateDir(profile_dir) == false) {    return false;  }  // load audio profiles - make sure there is a default profile  m_audio_profile_list = new CAudioProfileList(profile_dir);  m_audio_profile_list->Load();  if (m_audio_profile_list->GetCount() == 0 ||      m_audio_profile_list->FindProfile("default") == NULL) {    if (m_audio_profile_list->CreateConfig("default") == false) {      error_message("Can't create audio default profile");      return false;    } else {      debug_message("Created default audio profile");    }  }  snprintf(profile_dir, PATH_MAX, "%s/Text", base);  if (CheckandCreateDir(profile_dir) == false) {    return false;  }  // load text profiles - make sure there is a default profile  m_text_profile_list = new CTextProfileList(profile_dir);  m_text_profile_list->Load();  if (m_text_profile_list->GetCount() == 0 ||      m_text_profile_list->FindProfile("default") == NULL) {    if (m_text_profile_list->CreateConfig("default") == false) {      error_message("Can't create text default profile");      return false;    } else {      debug_message("Created default text profile");    }  }  // load streams  d = m_pConfig->GetStringValue(CONFIG_APP_STREAM_DIRECTORY);  if (d != NULL) {    strcpy(base, d);  } else {    GetHomeDirectory(base);    strcat(base, ".mp4live_d/Streams");  }  if (CheckandCreateDir(base) == false) {    return false;  }  m_stream_list = new CMediaStreamList(base,				       m_video_profile_list,				       m_audio_profile_list,				       m_text_profile_list);  m_stream_list->Load();  if (m_stream_list->GetCount() == 0) {    if (m_stream_list->CreateConfig("default") == false) {      error_message("Can't create default stream");    } else {      debug_message("Created default stream");    }  }  return true;}// ValidateAndUpdateStreams is called when a change is made to a // profile, or a new profile is selected in a stream// It will check the addresses, and make sure that the source has the// "max" valuesvoid CAVMediaFlow::ValidateAndUpdateStreams (void){  // Check the streams addresses  CMediaStream *s = m_stream_list->GetHead();  while (s != NULL) {    ValidateIpAddressAndPort(m_stream_list, s, 			     STREAM_VIDEO_PROFILE, STREAM_VIDEO_ADDR_FIXED,			     STREAM_VIDEO_DEST_ADDR, STREAM_VIDEO_DEST_PORT);    ValidateIpAddressAndPort(m_stream_list, s, 			     STREAM_AUDIO_PROFILE, STREAM_AUDIO_ADDR_FIXED,			     STREAM_AUDIO_DEST_ADDR, STREAM_AUDIO_DEST_PORT);    ValidateIpAddressAndPort(m_stream_list, s, 			     STREAM_TEXT_PROFILE, STREAM_TEXT_ADDR_FIXED,			     STREAM_TEXT_DEST_ADDR, STREAM_TEXT_DEST_PORT);    s = s->GetNext();  }  s = m_stream_list->GetHead();  uint32_t max_w = 0, max_h = 0, max_sample_rate = 0, max_chans = 0;  bool have_video = false, have_audio = false, have_text = false;  while (s != NULL) {    // get the maximum width and maximum height    if (s->GetBoolValue(STREAM_VIDEO_ENABLED)) {      have_video = true;      max_w = 	MAX(max_w, s->GetVideoProfile()->GetIntegerValue(CFG_VIDEO_WIDTH));      max_h = 	MAX(max_h, s->GetVideoProfile()->GetIntegerValue(CFG_VIDEO_HEIGHT));    }    // get the max channels and sampling rate    if (s->GetBoolValue(STREAM_AUDIO_ENABLED)) {      have_audio = true;      uint32_t orig_rate = 	s->GetAudioProfile()->GetIntegerValue(CFG_AUDIO_SAMPLE_RATE);      uint32_t ret_rate;      ret_rate = m_pConfig->m_audioCapabilities->CheckSampleRate(orig_rate);      if (ret_rate != orig_rate) {	error_message("Audio Profile %s illegal sample rate %u changed to %u", 		      s->GetAudioProfile()->GetName(), 		      orig_rate, ret_rate);	s->GetAudioProfile()->SetIntegerValue(CFG_AUDIO_SAMPLE_RATE, 					      ret_rate);      }      max_sample_rate = MAX(max_sample_rate, ret_rate);      max_chans = 	MAX(max_chans, 	    s->GetAudioProfile()->GetIntegerValue(CFG_AUDIO_CHANNELS));    }    if (s->GetBoolValue(STREAM_TEXT_ENABLED)) {      have_text = true;    }    createStreamSdp(m_pConfig, s);    s = s->GetNext();  }  m_pConfig->SetBoolValue(CONFIG_AUDIO_ENABLE, have_audio);  m_pConfig->SetBoolValue(CONFIG_TEXT_ENABLE, have_text);  m_pConfig->SetBoolValue(CONFIG_VIDEO_ENABLE, have_video);  // streams should all be loaded.  if (max_chans > 0) {    m_pConfig->SetIntegerValue(CONFIG_AUDIO_CHANNELS,			       max_chans);    m_pConfig->SetIntegerValue(CONFIG_AUDIO_SAMPLE_RATE,			       max_sample_rate);  }  if (max_w != 0) {    m_pConfig->SetIntegerValue(CONFIG_VIDEO_RAW_WIDTH,			       max_w);    m_pConfig->SetIntegerValue(CONFIG_VIDEO_RAW_HEIGHT,			       max_h);  }  m_pConfig->Update();  m_pConfig->WriteToFile();}// Startvoid CAVMediaFlow::Start(void){  if (m_started || m_pConfig == NULL) {    return;  }    // Create audio and video sources  if (m_pConfig->GetBoolValue(CONFIG_AUDIO_ENABLE)) {    m_audioSource = CreateAudioSource(m_pConfig, m_videoSource);  }  if (m_pConfig->GetBoolValue(CONFIG_TEXT_ENABLE)) {    m_textSource = CreateTextSource(m_pConfig);    debug_message("Created text source %p", m_textSource);  }  if (m_pConfig->GetBoolValue(CONFIG_VIDEO_ENABLE)       && m_videoSource == NULL) {    debug_message("start - creating video source");    m_videoSource = CreateVideoSource(m_pConfig);    if (m_audioSource != NULL) {      m_audioSource->SetVideoSource(m_videoSource);    }  }  m_maxAudioSamplesPerFrame = 0;  CMediaStream *s;  s = m_stream_list->GetHead();  // Create the components for each stream.  This make sure  // that no more than 1 instance of a profile is being encoded.  while (s != NULL) {    CAudioEncoder *ae_ptr = NULL;    CVideoEncoder *ve_ptr = NULL;    CTextEncoder *te_ptr = NULL;    if (s->GetBoolValue(STREAM_VIDEO_ENABLED)) {      // see if profile has already been started      ve_ptr = FindOrCreateVideoEncoder(s->GetVideoProfile());      s->SetVideoEncoder(ve_ptr);      m_pConfig->SetBoolValue(CONFIG_VIDEO_ENABLE, true);    }    if (s->GetBoolValue(STREAM_AUDIO_ENABLED)) {      // see if profile has already been started      ae_ptr = FindOrCreateAudioEncoder(s->GetAudioProfile());      s->SetAudioEncoder(ae_ptr);      m_pConfig->SetBoolValue(CONFIG_AUDIO_ENABLE, true);      // when we start the encoder, we will have to pass the channels      // configured, as well as the initial sample rate (basically,       // replicate SetAudioSrc here...    }    if (s->GetBoolValue(STREAM_TEXT_ENABLED)) {      // see if profile has already been started      te_ptr = FindOrCreateTextEncoder(s->GetTextProfile());      s->SetTextEncoder(te_ptr);      m_pConfig->SetBoolValue(CONFIG_TEXT_ENABLE, true);    }    if (s->GetBoolValue(STREAM_TRANSMIT)) {      // check if transmitter has been started on encoder      // create rtp destination, add to transmitter      if (ve_ptr != NULL) {	ve_ptr->AddRtpDestination(s,				  m_pConfig->GetBoolValue(CONFIG_RTP_DISABLE_TS_OFFSET),				  m_pConfig->GetIntegerValue(CONFIG_RTP_MCAST_TTL));      }      if (ae_ptr != NULL) {	ae_ptr->AddRtpDestination(s,				  m_pConfig->GetBoolValue(CONFIG_RTP_DISABLE_TS_OFFSET),				  m_pConfig->GetIntegerValue(CONFIG_RTP_MCAST_TTL));      }      if (te_ptr != NULL) {	te_ptr->AddRtpDestination(s,				  m_pConfig->GetBoolValue(CONFIG_RTP_DISABLE_TS_OFFSET),				  m_pConfig->GetIntegerValue(CONFIG_RTP_MCAST_TTL));      }      createStreamSdp(m_pConfig, s);    }    if (s->GetBoolValue(STREAM_RECORD)) {      // create file sink, add to above encoders.      CMediaSink *recorder = s->CreateFileRecorder(m_pConfig);      if (ve_ptr != NULL) {	ve_ptr->AddSink(recorder);      }      if (ae_ptr != NULL) {	ae_ptr->AddSink(recorder);      }      if (te_ptr != NULL) {	te_ptr->AddSink(recorder);      }    }    s = s->GetNext();  }    if (m_audioSource) {    m_audioSource->SetAudioSrcSamplesPerFrame(m_maxAudioSamplesPerFrame);    debug_message("Setting source sample per frame %u", m_maxAudioSamplesPerFrame);  }  // If we need raw stuff, we do it here  if (m_pConfig->GetBoolValue(CONFIG_RAW_ENABLE)) {    m_rawSink = new CRawFileSink();    m_rawSink->SetConfig(m_pConfig);    if (m_audioSource != NULL) {      m_audioSource->AddSink(m_rawSink);    }    if (m_videoSource != NULL) {      m_videoSource->AddSink(m_rawSink);    }    m_rawSink->StartThread();    m_rawSink->Start();  }  if (m_pConfig->GetBoolValue(CONFIG_RECORD_RAW_IN_MP4)) {    if (m_pConfig->GetBoolValue(CONFIG_RECORD_RAW_IN_MP4_VIDEO) ||	m_pConfig->GetBoolValue(CONFIG_RECORD_RAW_IN_MP4_AUDIO)) {      m_mp4RawRecorder = new CMp4Recorder(NULL);      m_mp4RawRecorder->SetConfig(m_pConfig);      if (m_audioSource != NULL &&	  m_pConfig->GetBoolValue(CONFIG_RECORD_RAW_IN_MP4_AUDIO)) {	m_audioSource->AddSink(m_mp4RawRecorder);      }      if (m_videoSource != NULL &&	  m_pConfig->GetBoolValue(CONFIG_RECORD_RAW_IN_MP4_VIDEO)) {	m_videoSource->AddSink(m_mp4RawRecorder);      }      m_mp4RawRecorder->StartThread();      m_mp4RawRecorder->Start();    }  }  // start encoders and any sinks...  This may result in some sinks  // file, in particular, receiving multiple starts  CMediaCodec *mc = m_video_encoder_list;  if (mc == NULL && m_videoSource != m_audioSource) {    delete m_videoSource;    m_videoSource = NULL;  }  while (mc != NULL) {    mc->Start();    mc->StartSinks();    mc = mc->GetNext();  }  mc = m_audio_encoder_list;  while (mc != NULL) {    mc->Start();    mc->StartSinks();    mc = mc->GetNext();  }  mc = m_text_encoder_list;  while (mc != NULL) {    mc->Start();    mc->StartSinks();    mc = mc->GetNext();  }  // finally, start sources...  if (m_videoSource && m_videoSource == m_audioSource) {    m_videoSource->Start();  } else {    if (m_audioSource) {      m_audioSource->Start();    }    if (m_videoSource) {      m_videoSource->Start();    }  }    if (m_textSource != NULL) {    m_textSource->Start();  }  if (m_videoSource) {    // force video source to generate a key frame    // so that sinks can quickly sync up    m_videoSource->RequestKeyFrame(0);  }    m_started = true;}// FindOrCreateVideoEncoder - create a new encoder, or return// one already on the listCVideoEncoder *CAVMediaFlow::FindOrCreateVideoEncoder (CVideoProfile *vp,						       bool create){  const char *vp_name = vp->GetName();  CVideoEncoder *ve_ptr = m_video_encoder_list;  while (ve_ptr != NULL) {    if (strcmp(vp_name, ve_ptr->GetProfileName()) == 0) {      return ve_ptr;    }    ve_ptr = ve_ptr->GetNext();  }   if (create == false) return NULL;  ve_ptr =     VideoEncoderCreate(vp, 		       m_pConfig->GetIntegerValue(CONFIG_RTP_PAYLOAD_SIZE), 		       m_video_encoder_list /* TODO realTime */);  m_video_encoder_list = ve_ptr;  ve_ptr->StartThread();  m_videoSource->AddSink(ve_ptr);  debug_message("Added video encoder %s", vp_name);  return ve_ptr;}  CAudioEncoder *CAVMediaFlow::FindOrCreateAudioEncoder (CAudioProfile *ap){  const char *ap_name = ap->GetName();  CAudioEncoder *ae_ptr = m_audio_encoder_list;   while (ae_ptr != NULL) {    if (strcmp(ap_name, ae_ptr->GetProfileName()) == 0) {      return ae_ptr;    }    ae_ptr = ae_ptr->GetNext();  }    ae_ptr = AudioEncoderCreate(ap, m_audio_encoder_list, 			      m_pConfig->GetIntegerValue(CONFIG_AUDIO_CHANNELS),			      m_pConfig->GetIntegerValue(CONFIG_AUDIO_SAMPLE_RATE),			      m_pConfig->GetIntegerValue(CONFIG_RTP_PAYLOAD_SIZE));  m_audio_encoder_list = ae_ptr;  // need to init, find max samples here..  ae_ptr->Init();  m_maxAudioSamplesPerFrame = MAX(m_maxAudioSamplesPerFrame, 				  ae_ptr->GetSamplesPerFrame());  ae_ptr->StartThread();  m_audioSource->AddSink(ae_ptr);  debug_message("Added audio encoder %s", ap_name);  return ae_ptr;}CTextEncoder *CAVMediaFlow::FindOrCreateTextEncoder (CTextProfile *tp){  const char *tp_name = tp->GetName();  CTextEncoder *te_ptr = m_text_encoder_list;   while (te_ptr != NULL) {    if (strcmp(tp_name, te_ptr->GetProfileName()) == 0) {      return te_ptr;    }    te_ptr = te_ptr->GetNext();  }    te_ptr =     TextEncoderCreate(tp, 		      m_pConfig->GetIntegerValue(CONFIG_RTP_PAYLOAD_SIZE), 		      m_text_encoder_list);  m_text_encoder_list = te_ptr;  // need to init, find max samples here..  te_ptr->StartThread();  m_textSource->AddSink(te_ptr);  debug_message("Added text encoder %s", tp_name);  return te_ptr;}// AddStream - called when we have a new stream from the GUIbool CAVMediaFlow::AddStream (const char *name){  if (m_started) {    return false;  }  CMediaStream *ms = m_stream_list->FindStream(name);  if (ms != NULL) {    error_message("Stream %s already exists\n", name);    return false;  }  if (m_stream_list->CreateConfig(name) == false) {    return false;  }  ValidateAndUpdateStreams();  return true;}bool CAVMediaFlow::DeleteStream (const char *name, bool remove_file){  char filename[PATH_MAX];  if (m_started) {    return false;  }  CMediaStream *ms = m_stream_list->FindStream(name);  if (ms == NULL) {    error_message("Cannot find stream %s to delete", name);    return false;  }  if (m_stream_list->GetCount() == 1) {    error_message("Cannot delete last stream %s", name);    return false;  }  m_stream_list->RemoveEntryFromList(ms);  strcpy(filename, ms->GetFileName());  delete ms; // this will write the file settings  if (remove_file) {    unlink(filename);  }  ValidateAndUpdateStreams();  return true;}void CAVMediaFlow::RestartFileRecording (void){  if (m_started == false) return;  bool hint_tracks = m_pConfig->GetBoolValue(CONFIG_RECORD_MP4_HINT_TRACKS);  if (hint_tracks) {    error_message("Disabling writing of hint tracks for file record restart");  }  m_pConfig->SetBoolValue(CONFIG_RECORD_MP4_HINT_TRACKS, false);  CMediaStream *stream;  stream = m_stream_list->GetHead();  while (stream != NULL) {    stream->RestartFileRecording();    stream = stream->GetNext();  }  m_pConfig->SetBoolValue(CONFIG_RECORD_MP4_HINT_TRACKS, hint_tracks);}/* end file media_flow.cpp */	 

⌨️ 快捷键说明

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