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

📄 ffmpeg_audio.cpp

📁 彩信浏览器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		m_fmt.samplerate = m_con->sample_rate;	}	if (m_fmt.channels == 0) {			m_fmt.channels = m_con->channels;	}}common::durationffmpeg_decoder_datasource::get_dur(){	return m_src->get_dur();}// **************************** ffmpeg_resample_datasource *****************************ffmpeg_resample_datasource::ffmpeg_resample_datasource(audio_datasource *src, audio_format_choices fmts) :	m_src(src),	m_context_set(false),	m_resample_context(NULL),	m_event_processor(NULL),	m_client_callback(NULL),	m_in_fmt(src->get_audio_format()),	m_out_fmt(fmts.best()){	ffmpeg_init();	AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::ffmpeg_resample_datasource()->0x%x m_buffer=0x%x", (void*)this, (void*)&m_buffer);#ifdef RESAMPLE_READ_ALL	m_buffer.set_max_size(0);#endif}ffmpeg_resample_datasource::~ffmpeg_resample_datasource() {	stop();}voidffmpeg_resample_datasource::stop() {	m_lock.enter();	int oldrefcount = get_ref_count();	AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::stop(0x%x)", (void*)this);	if (m_src) {		m_src->stop();		int rem = m_src->release();		if (rem) lib::logger::get_logger()->debug("ffmpeg_resample_datasource::stop(0x%x): m_src refcount=%d", (void*)this, rem); 		m_src = NULL;	} else {		AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::stop(0x%x): m_src already NULL", (void*)this);	}	m_src = NULL;	if (m_resample_context) audio_resample_close(m_resample_context);	m_resample_context = NULL;	if (m_client_callback) delete m_client_callback;	m_client_callback = NULL;	AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::stop(0x%x) refcount was %d is %d", (void*)this, oldrefcount, get_ref_count());	m_lock.leave();}voidffmpeg_resample_datasource::data_avail(){	m_lock.enter();	int sz;		int cursize = 0;	AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail(0x%x) refcount is %d", (void*)this, get_ref_count());	if (!m_src) {		AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail(0x%x): already stopping", (void*)this);		m_lock.leave();					return;	}	// We now have enough information to determine the resample parameters	if (!m_context_set) {		m_in_fmt = m_src->get_audio_format();		assert(m_in_fmt.bits == 16);		assert(m_out_fmt.bits == 16);		AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource: initializing context: inrate, ch=%d, %d, outrate, ch=%d, %d", m_in_fmt.samplerate,  m_in_fmt.channels, m_out_fmt.samplerate,  m_out_fmt.channels);		m_resample_context = audio_resample_init(m_out_fmt.channels, m_in_fmt.channels, m_out_fmt.samplerate,m_in_fmt.samplerate);		m_context_set = true;	}	if(m_src) {		sz = m_src->size();	} else {		lib::logger::get_logger()->debug("Internal error: ffmpeg_audio_datasource::data_avail: No datasource");		lib::logger::get_logger()->warn(gettext("Programmer error encountered during audio playback"));		m_lock.leave();					return;	}		if (m_resample_context) {	// Convert all the input data we have available. We make an educated guess at the number of bytes	// this will produce on output.		cursize = sz;		// Don't feed to much data to the resampler, it doesn't like to do lists ;-)		if (cursize > INBUF_SIZE) 			cursize = INBUF_SIZE;				AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail: cursize=%d, sz=%d, in channels=%d", cursize,sz,m_in_fmt.channels);		int insamples = cursize / (m_in_fmt.channels * sizeof(short));	// integer division !!!!		if (insamples * m_in_fmt.channels * sizeof(short) != (size_t)cursize) {			lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail: warning: incomplete samples: %d", cursize);		}				timestamp_t tmp = (timestamp_t)((insamples+1) * m_out_fmt.samplerate * m_out_fmt.channels * sizeof(short) / m_in_fmt.samplerate);		timestamp_t outsz = tmp;				if (!cursize && !m_src->end_of_file()) {			AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail(0x%x): no data available, not end-of-file!", (void*)this);			m_lock.leave();						return;		}		assert( cursize || m_src->end_of_file());		//if (sz & 1) lib::logger::get_logger()->warn("ffmpeg_resample_datasource::data_avail: warning: oddsized datasize %d", sz);		if (!m_buffer.buffer_full()) {			AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail(): m_src->get_read_ptr() m_src=0x%x, this=0x%x",(void*) m_src, (void*) this);			short int *inbuf = (short int*) m_src->get_read_ptr();			short int *outbuf = (short int*) m_buffer.get_write_ptr(outsz);			if (!outbuf) {				lib::logger::get_logger()->debug("Internal error: ffmpeg_audio_datasource::data_avail: no room in output buffer");				lib::logger::get_logger()->warn(gettext("Programmer error encountered during audio playback"));				m_src->readdone(0);				m_buffer.pushdata(0);			}			if (inbuf && outbuf && insamples > 0) {				AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail: sz=%d, insamples=%d, outsz=%d, inbuf=0x%x, outbuf=0x%x", cursize, insamples, outsz, inbuf, outbuf);				int outsamples = audio_resample(m_resample_context, outbuf, inbuf, insamples);				AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail(): putting %d bytes in %d bytes buffer space", outsamples*m_out_fmt.channels*sizeof(short), outsz);				assert(outsamples*m_out_fmt.channels*sizeof(short) <= outsz);				m_buffer.pushdata(outsamples*m_out_fmt.channels*sizeof(short));				AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail(): calling m_src->readdone(%d) this=0x%x", insamples*m_in_fmt.channels*sizeof(short), (void*) this);				m_src->readdone(insamples*m_in_fmt.channels*sizeof(short));			} else {									AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail(): calling m_src->readdone(0) m_src=0x%x, this=0x%x",  (void*) m_src, (void*) this);				m_src->readdone(0);				m_buffer.pushdata(0);			}		}		// Restart reading if we still have room to accomodate more data		if (!m_src->end_of_file() && m_event_processor && !m_buffer.buffer_full()) {			lib::event *e = new resample_callback(this, &ffmpeg_resample_datasource::data_avail);			AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail(): calling m_src->start(), refcount=%d", get_ref_count());			m_src->start(m_event_processor, e);#ifdef RESAMPLE_READ_ALL			// workaround for sdl bug: if RESAMPLE_READ_ALL is defined we continue			// reading until we have all data			m_lock.leave();			return;#endif /* RESAMPLE_READ_ALL */		} else {			AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail: not calling start: eof=%d m_ep=0x%x buffull=%d", 				(int)m_src->end_of_file(), (void*)m_event_processor, (int)m_buffer.buffer_full());		}		// If the client is currently interested tell them about data being available		if (m_client_callback && (m_buffer.buffer_not_empty() || _end_of_file() )) {			AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail(): calling client callback (%d, %d)", m_buffer.size(), _end_of_file());			assert(m_event_processor);			lib::event *clientcallback = m_client_callback;			m_client_callback = NULL;			m_event_processor->add_event(clientcallback, 0, ambulant::lib::ep_med);			//m_event_processor = NULL;		} else {			AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail(): No client callback!");		}	} else {		// Something went wrong during initialization, we just drop the data		// on the floor.		AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail(): No resample context, flushing data");		AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::data_avail(): m_src->readdone(%d) called m_src=0x%x, this=0x%x", sz, (void*) m_src, (void*) this);		m_src->readdone(sz);	}	m_lock.leave();}void ffmpeg_resample_datasource::readdone(int len){	m_lock.enter();	m_buffer.readdone(len);	AM_DBG lib::logger::get_logger()->debug("ffmpeg_decoder_datasource::readdone: done with %d bytes", len);	if (!m_src->end_of_file() && m_event_processor && !m_buffer.buffer_full()) {		AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::readdone: calling m_src->start() again");		lib::event *e = new resample_callback(this, &ffmpeg_resample_datasource::data_avail);		m_src->start(m_event_processor, e);	}	m_lock.leave();}bool ffmpeg_resample_datasource::end_of_file(){	m_lock.enter();	bool rv = _end_of_file();	m_lock.leave();	return rv;}bool ffmpeg_resample_datasource::_end_of_file(){	// private method - no need to lock	if (m_buffer.buffer_not_empty()) return false;	if (m_src)		return m_src->end_of_file();		return true;}boolffmpeg_resample_datasource::_src_end_of_file() const{	// private mathod - no need to lock			if (m_src)		return m_src->end_of_file();		return true;}bool ffmpeg_resample_datasource::buffer_full(){	m_lock.enter();	bool rv = m_buffer.buffer_full();	m_lock.leave();	return rv;}	timestamp_tffmpeg_resample_datasource::get_clip_end(){	return m_src->get_clip_end();}timestamp_tffmpeg_resample_datasource::get_clip_begin(){	return m_src->get_clip_begin();}char* ffmpeg_resample_datasource::get_read_ptr(){	m_lock.enter();	char *rv = m_buffer.get_read_ptr();	m_lock.leave();	return rv;}int ffmpeg_resample_datasource::size() const{	const_cast <ffmpeg_resample_datasource*>(this)->m_lock.enter();	int rv = m_buffer.size();	const_cast <ffmpeg_resample_datasource*>(this)->m_lock.leave();	return rv;}	void ffmpeg_resample_datasource::start(ambulant::lib::event_processor *evp, ambulant::lib::event *callbackk){	m_lock.enter();	bool restart_input = false;		AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::start(): start(0x%x) called", this);	if (m_client_callback != NULL) {		delete m_client_callback;		m_client_callback = NULL;		AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::start(): m_client_callback already set!");	}		if ( m_buffer.buffer_not_empty() && _end_of_file() ) {		AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::start(): (%d  || %d) = %d ", _end_of_file(), m_buffer.buffer_not_empty(), _end_of_file() || m_buffer.buffer_not_empty());		// We have data (or EOF) available. Don't bother starting up our source again, in stead		// immedeately signal our client again		restart_input = false;		AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::start(): no restart EOF (or clipend reached) but no data available");		if (callbackk) {			assert(evp);			AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::start: trigger client callback");			evp->add_event(callbackk, 0, ambulant::lib::ep_med);		} else {			lib::logger::get_logger()->error("Internal error: ffmpeg_resample_datasource::start(): no client callback!");			lib::logger::get_logger()->warn(gettext("Programmer error encountered during audio playback"));		}	} else {		// We have no data available. Start our source, and in our data available callback we		// will signal the client.		AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::start(): (%d && %d) = %d ", !_end_of_file(), !m_buffer.buffer_full(), !_end_of_file() && !m_buffer.buffer_full());		restart_input = true;		m_client_callback = callbackk;		m_event_processor = evp;	}	// Also restart our source if we still have room and there is	// data to read.	AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::start(): (%d && %d) = %d ", !_end_of_file(), !m_buffer.buffer_full(), !_end_of_file() && !m_buffer.buffer_full());	if ( !_src_end_of_file() && !m_buffer.buffer_full() ) {		restart_input = true;		AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::start(): no EOF and buffer is not full so we need to do a restart, (%d && %d) = %d ", !_end_of_file(), !m_buffer.buffer_full(), !_end_of_file() && !m_buffer.buffer_full());	}		if (restart_input) {		// Restart the input stream		lib::event *e = new resample_callback(this, &ffmpeg_resample_datasource::data_avail);		AM_DBG lib::logger::get_logger()->debug("ffmpeg_resample_datasource::start(): calling m_src->start(0x%x, 0x%x)", m_event_processor, e);		m_src->start(evp,  e);	}		m_lock.leave();}common::durationffmpeg_resample_datasource::get_dur(){	common::duration rv(false, 0.0);	m_lock.enter();	if (m_src)		rv = m_src->get_dur();	m_lock.leave();	return rv;}

⌨️ 快捷键说明

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