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

📄 mpeg_audio.cpp

📁 linux下实现视频播放的播放器
💻 CPP
字号:
/* *  Copyright (C) 2005-2007  gulikoza * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* $Id$ */#include "iptv.h"#define USES_BASECLASS#include "video.h"#include "wxgui/StreamInfo.h"#include "mad.h"//#define DEBUG#include "log.h"#define MODULE "mpeg_audio"#define SOUNDBUFFER 16384static inline int scale(mad_fixed_t sample){    // Round    sample += (1L << (MAD_F_FRACBITS - 16));    // Clip    if(sample >= MAD_F_ONE)	sample = MAD_F_ONE - 1;    else if(sample < -MAD_F_ONE)	sample = -MAD_F_ONE;    // Quantize    return sample >> (MAD_F_FRACBITS + 1 - 16);}int mpeg_audio::Run(){    mad_synth   synth;    mad_stream  stream;    mad_frame   frame;    mad_timer_t timer;    unsigned int frequency = 0;    Audioinfo * audio = (Audioinfo*)filterinfo;    unsigned char * soundbuf = (unsigned char*)_aligned_malloc((sizeof(char)*SOUNDBUFFER)+8, 64);    unsigned int soundoff = 0;#if (C_HAVE_WXGUI)    Uint32 frameStartTicks;#endif    if(soundbuf == NULL) {	ERROR_MSG("Error allocating memory!");	return 0;    }    mad_synth_init (&synth);    mad_stream_init(&stream);    mad_frame_init (&frame);    ERROR_MSG("(ThreadID: %u) init complete", SDL_ThreadID());    LOG_MSG("Buffer address 0x%x", buffer);    while(ThreadRun()) {	unsigned int m_size;	unsigned int offset, audiopts;	m_size = fifo->GetPacket(&offset, &audiopts);	if((m_size == 0) || (m_size > buffersize)) {	    LOG_MSG("Error invalid packet size: %d", m_size);	    SDL_Delay(10);	    continue;	}	LockBuffer();	roffset = offset;        if(!SDL_SemValue(data))	    SDL_SemPost(data);	UnlockBuffer();	if(m_size > SOUNDBUFFER-soundoff) {	    ERROR_MSG("PES size %d too large (%d), contact the author!", m_size, SOUNDBUFFER-soundoff);	    SDL_Delay(10);	    continue;	}	// Copy into temporary decoding buffer	SDL_memcpy(soundbuf+soundoff, buffer+offset, m_size);	DEBUG_MSG("%d bytes added to the buffer, %d total", m_size, soundoff+m_size);	// MAD will only decode up to frame boundry	// (leave a part of next frame in the buffer)	mad_stream_buffer(&stream, soundbuf, soundoff+m_size+8);	if(audiopts)	    mad_timer_set(&timer, audiopts/1000, audiopts%1000, 1000);	while(true) {	    if(stream.next_frame > soundbuf+soundoff+m_size-1) {		soundoff = 0;		break;	    }	    LOG_MSG("Decode frame at: 0x%x (%d bytes left)", stream.next_frame, soundbuf+soundoff+m_size-stream.next_frame);	    if(mad_frame_decode(&frame, &stream) == -1) {		if(stream.error == MAD_ERROR_BUFLEN) {		    LOG_MSG("ERROR: End of buffer, frame 0x%x!", stream.next_frame);		    // Copy remaning data		    SDL_memcpy(soundbuf, stream.next_frame, soundbuf+soundoff+m_size-stream.next_frame);		    soundoff = soundbuf+soundoff+m_size-stream.next_frame;		    break;		}		if(!MAD_RECOVERABLE(stream.error)) {		    ERROR_MSG("Critical error while decoding frame!");		    return -1;		}		ERROR_MSG("Error while decoding frame: 0x%x!", stream.error);		// Really needed?		//mad_timer_add(&timer, frame.header.duration);		continue;	    }	    mad_synth_frame(&synth, &frame);	    // Decoded channels	    const mad_fixed_t *left_ch  = synth.pcm.samples[0];	    const mad_fixed_t *right_ch = synth.pcm.samples[1];	    unsigned int decoded = synth.pcm.length;#if (C_HAVE_WXGUI)	    Uint32 frameTimeTaken = SDL_GetTicks() - frameStartTicks;	    // Update ~twice per second	    if(frameTimeTaken > 500) {		if(gui.wxStreamInfo != NULL)		    gui.wxStreamInfo->UpdateAudioStream(frame.header.samplerate, frame.header.bitrate);		frameStartTicks = SDL_GetTicks();	    }#endif	    if((frequency != synth.pcm.samplerate) || (audio->stereo != (synth.pcm.channels-1))) {	        SDL_Event event;	        event.type = SDL_USEREVENT+2;	        event.user.data1 = (void*)((intptr_t)synth.pcm.samplerate);		event.user.data2 = (void*)((intptr_t)synth.pcm.channels);		audio->stereo = (synth.pcm.channels - 1);		if(!audio->stereo) audio->mode = 0;	        SDL_PushEvent(&event);#ifdef SEM_SILENT		SDL_SemWait(audio->audio_change);#else                while(SDL_SemWaitTimeout(audio->audio_change, 1000) == SDL_MUTEX_TIMEDOUT) {                    ERROR_MSG("Semaphore timeout expired, line: %d, thread: %u", __LINE__, SDL_ThreadID());		}#endif		frequency = synth.pcm.samplerate;	    }	    SDL_LockAudio();	    DEBUG_MSG("Audio PTS: %d, timer: %.3fs", audiopts,		    (float)mad_timer_count(timer, MAD_UNITS_MILLISECONDS)/1000.0f);	    LOG_MSG("Decoded %d samples of data (%d), samplerate: %d, buffer offset %d", decoded,		    frame.header.bitrate, synth.pcm.samplerate, audio->w_pos);	    // Samples output	    float * output = audio->data + audio->w_pos;	    unsigned int i = (BUFFERSIZE>>2) - audio->w_pos;	    unsigned int m_samples = 0;write_buffer:	    if(audio->w_pos == 0) {		audiopts  = mad_timer_count(timer, MAD_UNITS_MILLISECONDS);		audiopts += (1000*m_samples)/synth.pcm.samplerate;		audio->ptsstart = audiopts;	    }	    i = (i > decoded<<1 ? decoded : i>>1);	    decoded -= i;	    m_samples += i;	    audio->w_pos += i<<1;	    if((audio->mode == 0) && (synth.pcm.channels - 1)) {		DEBUG_MSG("Writing %d samples (stereo), samples left %d", i, decoded);		while(i) {		    *output++ = scale(*left_ch++)  / (1.0 * 0x8000);		    *output++ = scale(*right_ch++) / (1.0 * 0x8000);		    i--;		}	    } else {		if((audio->mode == 2) && (synth.pcm.channels - 1)) left_ch = right_ch;		DEBUG_MSG("Writing %d samples (mono), samples left %d", i, decoded);		while(i) {		    float tmp = scale(*left_ch++) / (1.0 * 0x8000);		    *output++ = tmp;		    *output++ = tmp;		    i--;		}	    }	    // If samples are still in the buffer...	    if(decoded) {		DEBUG_MSG("Audio buffer wrap");		i = BUFFERSIZE>>2;		audio->size = audio->w_pos;		audio->w_pos = 0;		output = audio->data;		goto write_buffer;	    }	    if(audio->size < audio->w_pos)		audio->size = audio->w_pos;	    DEBUG_MSG("Buffer written to pos: %d", audio->w_pos);	    SDL_UnlockAudio();	    mad_timer_add(&timer, frame.header.duration);	}	LOG_MSG("Sound offset set to %d", soundoff);    }    _aligned_free(soundbuf);    mad_frame_finish (&frame);    mad_stream_finish(&stream);    ERROR_MSG("(ThreadID: %u) finish complete", SDL_ThreadID());    return 0;}

⌨️ 快捷键说明

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