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

📄 media_flow.cpp

📁 完整的RTP RTSP代码库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is MPEG4IP. *  * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2000-2005.  All Rights Reserved. *  * Contributor(s):  *		Dave Mackie		dmackie@cisco.com *		Bill May 		wmay@cisco.com */#include "mp4live.h"#include "media_flow.h"#include "audio_oss_source.h"#include "video_v4l_source.h"#include "file_mp4_recorder.h"#include "rtp_transmitter.h"#include "file_raw_sink.h"#include "mp4live_common.h"#include "video_encoder.h"#include "audio_encoder.h"#include "text_encoder.h"#include "text_encoder.h"#include "media_stream.h"#include "profile_video.h"#include "profile_audio.h"#include "profile_text.h"#include "text_source.h"CAVMediaFlow::CAVMediaFlow(CLiveConfig* pConfig){  m_pConfig = pConfig;  m_started = false;  m_videoSource = NULL;  m_audioSource = NULL;  m_textSource = NULL;  m_mp4RawRecorder = NULL;  m_rawSink = NULL;  m_video_profile_list = NULL;  m_audio_profile_list = NULL;  m_text_profile_list = NULL;  m_stream_list = NULL;  m_video_encoder_list = NULL;  m_audio_encoder_list = NULL;  m_text_encoder_list = NULL;  ReadStreams();  ValidateAndUpdateStreams();}CAVMediaFlow::~CAVMediaFlow() {  CAVMediaFlow::Stop();  if (m_videoSource != NULL) {    m_videoSource->StopThread();    delete m_videoSource;    m_videoSource = NULL;  }  if (m_stream_list != NULL) {    delete m_stream_list;    m_stream_list = NULL;  }  if (m_video_profile_list != NULL) {    delete m_video_profile_list;    m_video_profile_list = NULL;  }  if (m_audio_profile_list != NULL) {    delete m_audio_profile_list;    m_audio_profile_list = NULL;  }  if (m_text_profile_list != NULL) {    delete m_text_profile_list;    m_text_profile_list = NULL;  }}void CAVMediaFlow::Stop(void){	if (!m_started) {		return;	}	//debug_message("media flow - stop");	bool oneSource = (m_audioSource == m_videoSource);	// Stop the sources	if (m_audioSource) {	  m_audioSource->RemoveAllSinks();		m_audioSource->StopThread();		delete m_audioSource;		m_audioSource = NULL;	}	if (!m_pConfig->IsCaptureVideoSource()) {		if (m_videoSource && !oneSource) {		  debug_message("Stopping video source thread");		  m_videoSource->RemoveAllSinks();			m_videoSource->StopThread();			delete m_videoSource;		}		m_videoSource = NULL;	}	if (m_textSource) {	  m_textSource->RemoveAllSinks();	  m_textSource->StopThread();	  delete m_textSource;	  m_textSource = NULL;	  debug_message("Text stopped");	}	// stop the encoders - remove the sinks from the source	// This will stop the sinks, and deletes the rtp destinations	CMediaCodec *mc = m_video_encoder_list, *p;	while (mc != NULL) {	  //debug_message("stopping video profile %s", mc->GetProfileName());	  if (m_videoSource != NULL) {	    m_videoSource->RemoveSink(mc);	  }	  //	  debug_message("sinks removed");	  mc->StopThread();	  //debug_message("thread_stopped");	  mc->StopSinks();	  //debug_message("sinks stopped");	  p = mc;	  mc = mc->GetNext();	  delete p;	}	m_video_encoder_list = NULL;	mc = m_audio_encoder_list;	while (mc != NULL) {	  // debug_message("stopping audio profile %s", mc->GetProfileName());	  mc->StopThread();	  //debug_message("thread stopped");	  mc->StopSinks();	  //debug_message("stopping sinks");	  p = mc;	  mc = mc->GetNext();	  delete p;	}	m_audio_encoder_list = NULL;	mc = m_text_encoder_list;	while (mc != NULL) {	   debug_message("stopping text profile %s", mc->GetProfileName());	  mc->StopThread();	  debug_message("thread stopped");	  mc->StopSinks();	  debug_message("stopping sinks");	  p = mc;	  mc = mc->GetNext();	  delete p;	}	m_text_encoder_list = NULL;	// Now, stop the streams (stops and deletes file recorders	CMediaStream *stream;	stream = m_stream_list->GetHead();	while (stream != NULL) {	  stream->Stop();	  stream = stream->GetNext();	}	// Note - m_videoSource may still be active at this point	// be sure to remove any sinks attached to it.	// any other sinks that were added should be stopped here.	if (m_rawSink) {	  if (m_videoSource != NULL) {	    m_videoSource->RemoveSink(m_rawSink);	  }		m_rawSink->StopThread();		delete m_rawSink;		m_rawSink = NULL;	}			if (m_mp4RawRecorder != NULL) {	  if (m_videoSource != NULL) {	    m_videoSource->RemoveSink(m_mp4RawRecorder);	  }	  m_mp4RawRecorder->StopThread();	  delete m_mp4RawRecorder;	  m_mp4RawRecorder = NULL;	}		m_started = false;	}void CAVMediaFlow::SetPictureControls(void){	if (m_videoSource) {		m_videoSource->SetPictureControls();	}}void CAVMediaFlow::SetAudioOutput(bool mute){	static int muted = 0;	static int lastVolume;	const char* mixerName = 		m_pConfig->GetStringValue(CONFIG_AUDIO_MIXER_NAME);	int mixer = open(mixerName, O_RDONLY);	if (mixer < 0) {		error_message("Couldn't open mixer %s", mixerName);		return;	}	if (mute) {		ioctl(mixer, SOUND_MIXER_READ_LINE, &lastVolume);		ioctl(mixer, SOUND_MIXER_WRITE_LINE, &muted);	} else {		int newVolume;		ioctl(mixer, SOUND_MIXER_READ_LINE, &newVolume);		if (newVolume == 0) {			ioctl(mixer, SOUND_MIXER_WRITE_LINE, &lastVolume);		}	}	close(mixer);}bool CAVMediaFlow::GetStatus(u_int32_t valueName, void* pValue) {	CMediaSource* source = NULL;	if (m_videoSource) {		source = m_videoSource;	} else if (m_audioSource) {		source = m_audioSource;	} else if (m_textSource) {	  source = m_textSource;	}	switch (valueName) {	case FLOW_STATUS_DONE: 		{		bool done = true;		if (m_videoSource) {			done = m_videoSource->IsDone();		}		if (m_audioSource) {			done = (done && m_audioSource->IsDone());		}		if (m_textSource) {		  done = (done && m_textSource->IsDone());		}		*(bool*)pValue = done;		}		break;	case FLOW_STATUS_PROGRESS:		if (source) {			*(float*)pValue = source->GetProgress();		} else {			*(float*)pValue = 0.0;		}		break;	default:	  return false;	}	return true;}// CheckandCreateDir - based on name, check if directory exists// if not, create it.  If so, check that it is a directorystatic bool CheckandCreateDir (const char *name){  struct stat statbuf;  if (stat(name, &statbuf) == 0) {    if (!S_ISDIR(statbuf.st_mode)) {      error_message("%s is not a directory", name);      return false;    }  } else {    if (mkdir(name, S_IRWXU) < 0) {      error_message("can't create directory \"%s\" - %s", 		    name, strerror(errno));      return false;    }  }  return true;}  /* * Check dup - checks for duplicates in media stream addresses. */static bool CheckDup (CMediaStream *orig, 		      CMediaStream *check,		      config_index_t profile_ix,		      config_index_t orig_addr_ix,		      config_index_t orig_port_ix,		      config_index_t check_profile_ix,		      config_index_t check_addr_ix,		      config_index_t check_port_ix){  // see if the address and port match  if (orig->GetIntegerValue(orig_port_ix) ==       check->GetIntegerValue(check_port_ix) &&      strcmp(orig->GetStringValue(orig_addr_ix),	     orig->GetStringValue(check_addr_ix)) == 0) {    // we have the same address:port    if (profile_ix == check_profile_ix) {      // See if the profiles match - if they do, no dup      if (strcmp(orig->GetStringValue(profile_ix),		 check->GetStringValue(check_profile_ix)) == 0) {	return false;      }    }     // we have an address:port match, and we are not on the same profile    return true;  }  return false;}// CheckAddressForDup - check audio, video and text addresses, unless the// stream matches.bool CheckAddressForDup (CMediaStreamList *stream_list, 			 CMediaStream *s,			 config_index_t profile_ix, 			 config_index_t addr_ix, 			 config_index_t port_ix){  CMediaStream *p = stream_list->GetHead();  while (p != NULL) {    if (p != s) {      if (CheckDup(s, p,		   profile_ix, addr_ix, port_ix, 		   STREAM_VIDEO_PROFILE, STREAM_VIDEO_DEST_ADDR, STREAM_VIDEO_DEST_PORT)) {	return true;      }      if (CheckDup(s, p,		   profile_ix, addr_ix, port_ix, 		   STREAM_AUDIO_PROFILE, STREAM_AUDIO_DEST_ADDR, STREAM_AUDIO_DEST_PORT)) {	return true;      }      if (CheckDup(s, p,		   profile_ix, addr_ix, port_ix, 		   STREAM_TEXT_PROFILE, STREAM_TEXT_DEST_ADDR, STREAM_TEXT_DEST_PORT)) {	return true;      }    }    p = p->GetNext();  }  return false;}// SetRestOfProfile - all streams that have matching profiles and do// not have fixed addresses to the same address:portvoid SetRestOfProfile (CMediaStream *s, 		       config_index_t profile,		       config_index_t fixed,		       config_index_t addr,		       config_index_t port){  CMediaStream *p = s->GetNext();  while (p != NULL) {    if (strcmp(p->GetStringValue(profile), s->GetStringValue(profile)) == 0) {      if (p->GetBoolValue(fixed) == false) {	p->SetStringValue(addr, s->GetStringValue(addr));	p->SetIntegerValue(port, s->GetIntegerValue(port));      }    }    p = p->GetNext();  }}// ValidateAddressAndPort does a number of things - verifies that the// address and port are in a valid range, set all streams with similiar// profiles to that address, and makes sure there are no duplicate addressesvoid ValidateIpAddressAndPort (CMediaStreamList *stream_list, 			       CMediaStream *s,			       config_index_t profile_ix, 			       config_index_t fixed_ix,			       config_index_t addr_ix, 			       config_index_t port_ix){  bool corrected;  debug_message("Checking %s %s %s %s:%u",		s->GetName(),		s->GetNameFromIndex(profile_ix),		s->GetStringValue(profile_ix),		s->GetStringValue(addr_ix),		s->GetIntegerValue(port_ix));  do {    if (ValidateIpAddress(s->GetStringValue(addr_ix)) == false) {      struct in_addr in;      debug_message("Stream %s %s address was invalid \"%s\"",		    s->GetName(),		    s->GetNameFromIndex(profile_ix),		    s->GetStringValue(addr_ix));      in.s_addr = GetRandomMcastAddress();      s->SetStringValue(addr_ix, inet_ntoa(in));      debug_message("changed to \"%s\"", s->GetStringValue(addr_ix));    }        if (s->GetIntegerValue(port_ix) >= 0xffff ||	ValidateIpPort(s->GetIntegerValue(port_ix)) == false) {      debug_message("Stream %s %s address was invalid %u",		    s->GetName(),		    s->GetNameFromIndex(profile_ix),		    s->GetIntegerValue(port_ix));      s->SetIntegerValue(port_ix, GetRandomPort());      debug_message("Changed to %u", s->GetIntegerValue(port_ix));    }    if (s->GetBoolValue(fixed_ix) == false) {      SetRestOfProfile(s, profile_ix, fixed_ix, addr_ix, port_ix);    }    corrected = CheckAddressForDup(stream_list, 				   s,				   profile_ix,				   addr_ix, 				   port_ix);    if (corrected == true) {      // keep address, move port - by setting port to 0, we will trigger      // the above       s->SetIntegerValue(port_ix, 0);    }  } while (corrected);}// ReadStreams - read all the profiles (audio and video), then reads// the streamsbool CAVMediaFlow::ReadStreams (void){  char base[PATH_MAX];   const char *d;  d = m_pConfig->GetStringValue(CONFIG_APP_PROFILE_DIRECTORY);  if (d != NULL) {    strcpy(base, d);  } else {    GetHomeDirectory(base);    strcat(base, ".mp4live_d");  }  if (CheckandCreateDir(base) == false)     return false;  // Load video profiles  Make sure there is a "default" profile  char profile_dir[PATH_MAX];  snprintf(profile_dir, PATH_MAX, "%s/Video", base);  if (CheckandCreateDir(profile_dir) == false) {    return false;  }  m_video_profile_list = new CVideoProfileList(profile_dir);  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 ||

⌨️ 快捷键说明

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