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

📄 mpeg_decoder.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 "libmpeg2/mpeg2.h"//#define DEBUG#include "log.h"#define MODULE "mpeg_decoder"int mpeg_decoder::Run(){    mpeg2dec_t *m_dec;    const mpeg2_info_t *m_info;    // Pitcure info    bool changed = false;    unsigned int w = 0, h = 0;    double aspect = 0.0;    // 4:2:0 or 4:2:2 ?    //bool mode422 = false;#if (C_HAVE_WXGUI)    long sliceSize;    Uint32 sliceStartTicks;#endif    if(SDL_HasMMX()) {	ERROR_MSG("Detected MMX capable CPU");	h |= MPEG2_ACCEL_X86_MMX;    }    // Set acceleration    mpeg2_accel(h);    w = h = 0;    // Init MPEG2 decoder    m_dec = mpeg2_init();    m_info = mpeg2_info(m_dec);    ERROR_MSG("(ThreadID: %u) init complete", SDL_ThreadID());    // Frame counter    int frames = 0;    double frame_period = 0.0;    // Target surface info    Frame frame;    Renderer * renderer;#if (C_HAVE_WXGUI)    sliceSize = 0;    sliceStartTicks = SDL_GetTicks();#endif    while(ThreadRun()) {	renderer = (Renderer*)filterinfo;	// Get next packet from the fifo queue	unsigned int offset, m_size, pts;	m_size = fifo->GetPacket(&offset, &pts);#if (C_HAVE_WXGUI)	sliceSize += m_size;#endif	if((m_size == 0) || (m_size > buffersize)) {	    LOG_MSG("Error invalid packet size: %d", m_size);	    SDL_Delay(10);	    continue;	}	LockBuffer();	roffset = offset;	LOG_MSG("Set roffset to %d, pts %d", offset, pts);	if(!SDL_SemValue(data))	    SDL_SemPost(data);	UnlockBuffer();	mpeg2_buffer(m_dec, buffer+offset, buffer+offset+m_size);	DEBUG_MSG("Buffer set to 0x%x-0x%x", buffer+offset, buffer+offset+m_size);	mpeg2_state_t state = mpeg2_parse(m_dec);	while(state != STATE_BUFFER) {	    switch(state) {		case STATE_BUFFER:		    DEBUG_MSG("STATE_BUFFER");		    break;		case STATE_INVALID:		    DEBUG_MSG("STATE_INVALID");		    break;		case STATE_GOP:		    DEBUG_MSG("GOP header found");		    DEBUG_MSG("User data (cc): %d", m_info->user_data_len);		    break;		case STATE_SEQUENCE:		    DEBUG_MSG("SEQUENCE header found");		    frame_period = (double)m_info->sequence->frame_period / 27000.0;		    LOG_MSG("Frame period: %.2f ms", frame_period);		    // Check for video size change		    if((w != m_info->sequence->picture_width) || (h != m_info->sequence->picture_height)			    || (aspect != m_info->sequence->aspect)) {			w = m_info->sequence->picture_width;			h = m_info->sequence->picture_height;			aspect = m_info->sequence->aspect;			LOG_MSG("New picture size: %dx%d, AR: %.2f", w, h, m_info->sequence->aspect);			if(m_info->sequence->height == m_info->sequence->chroma_height) {			    ERROR_MSG("Mpeg 4:2:2 not supported!");			    goto finish_thread;			}			changed = true;#if (C_HAVE_WXGUI)			// New video size			if(gui.wxStreamInfo != NULL)			    gui.wxStreamInfo->UpdateVideoStream(w, h, m_info->sequence->byte_rate * 8, aspect);			sliceSize = 0;			sliceStartTicks = SDL_GetTicks();#endif		    }		    // Set pitch & height		    frame.w = w; frame.h = h;		    frame.aspect = aspect;		    frame.pitch = ALIGN(frame.w, 16);		    frame.h = ALIGN(frame.h, 16);		    // Use custom buffers		    if(renderer) {			// Set the first 2 reference frames			renderer->LockData(&frame);			if(frame.id < 0) goto finish_thread;			mpeg2_custom_fbuf(m_dec, 1);			mpeg2_set_buf(m_dec, frame.data, (void*)((intptr_t)frame.id));			renderer->LockData(&frame);			if(frame.id < 0) goto finish_thread;			mpeg2_set_buf(m_dec, frame.data, (void*)((intptr_t)frame.id));		    }		    break;		case STATE_PICTURE:		    mpeg2_setPTS(m_dec, pts);#ifdef DEBUG		    switch(m_info->current_picture->flags&PIC_MASK_CODING_TYPE) {			case PIC_FLAG_CODING_TYPE_I:			    LOG_MSG("I frame, pts: %d", pts);			    break;			case PIC_FLAG_CODING_TYPE_P:			    LOG_MSG("P frame, pts: %d", pts);			    break;			case PIC_FLAG_CODING_TYPE_B:			    LOG_MSG("B frame, pts: %d", pts);			    break;			case PIC_FLAG_CODING_TYPE_D:			    LOG_MSG("D frame, pts: %d", pts);			    break;			default:			    LOG_MSG("Unknown frame, pts: %d", pts);			    break;		    }#endif		    pts = 0;		    // Set pitch & height		    frame.w = w; frame.h = h;		    frame.pitch = ALIGN(frame.w, 16);		    frame.h = ALIGN(frame.h, 16);		    if(renderer) {			renderer->LockData(&frame);			if(frame.id < 0) goto finish_thread;			mpeg2_set_buf(m_dec, frame.data, (void*)((intptr_t)frame.id));		    }		    break;		case STATE_END:		case STATE_SLICE: {		    DEBUG_MSG("SLICE found");		    if((m_info->display_fbuf) && (renderer)) {			if((frames == 0) &&			    (m_info->display_picture->flags&PIC_MASK_CODING_TYPE != PIC_FLAG_CODING_TYPE_I)) {			    renderer->UnlockData((int)PT2L(m_info->display_fbuf->id), NULL);			    break;			}			// Fill all real info			frame.aspect = aspect;			frame.time = frame_period;			frame.pts = m_info->display_picture->pts;			frame.changed = changed; changed = false;			renderer->UnlockData((int)PT2L(m_info->display_fbuf->id), &frame);			renderer->ReleaseData((int)PT2L(m_info->display_fbuf->id));			++frames;		    }		    else if((m_info->discard_fbuf) && (renderer)) {			renderer->UnlockData((int)PT2L(m_info->discard_fbuf->id), NULL);		    }#if (C_HAVE_WXGUI)		    Uint32 sliceTimeTaken = SDL_GetTicks() - sliceStartTicks;		    // Update ~twice per second		    if(sliceTimeTaken > 500) {			if(gui.wxStreamInfo != NULL)			    gui.wxStreamInfo->UpdateVideoActualBitrate((long)((double)sliceSize * 8000.0 / (double)sliceTimeTaken));			sliceSize = 0;			sliceStartTicks = SDL_GetTicks();		    }#endif		    break;		}		default:		    DEBUG_MSG("STATE 0x%x", state);		    break;	    } // switch	    state = mpeg2_parse(m_dec);	} // while(state != STATE_BUFFER)    } // while(ThreadRun())finish_thread:    if(m_dec)	mpeg2_close(m_dec);    m_dec = NULL;    if(renderer)	renderer->FlushBuffers();    ERROR_MSG("(ThreadID: %u) finish complete", SDL_ThreadID());    return 0;}

⌨️ 快捷键说明

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