📄 mpeg_decoder.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 + -