?? libds_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"#if (C_HAS_DIRECTSHOW)#include "h264.h"#include "libdshow/DS.h"#include "libdshow/DS_VideoDecoder.h"//#define DEBUG#include "log.h"#define MODULE "libds_decoder"#define IMGFMT_YV12 0x32315659#define IMGFMT_YUY2 0x32595559static GUID CLSID_CoreAVC = {0x9571a4b, 0xf1fe, 0x4c60, {0x97, 0x60, 0xde, 0x6d, 0x31, 0x0c, 0x7c, 0x31}};int libds_decoder::Run(){ // Codec DS_VideoDecoder * dshowdec; // Pitcure info unsigned int w = 0, h = 0; // Use some sane defaults incase stream does not have this info double aspect = 16.0/9.0; double time = 40.0;#if (C_HAVE_WXGUI) long frameSize; Uint32 frameStartTicks;#endif BITMAPINFOHEADER bih; SampleProcUserData dsinfo; bih.biSize = sizeof(BITMAPINFOHEADER); bih.biWidth = 1920; bih.biHeight = 1088; bih.biPlanes = 0; bih.biBitCount = 0;// bih.biCompression = 0x31637661; // avc1 bih.biCompression = 0x31435641; // AVC1 bih.biSizeImage = 0; bih.biXPelsPerMeter = 0; bih.biYPelsPerMeter = 0; bih.biClrUsed = 0; bih.biClrImportant = 0; // Init codec dshowdec = DS_VideoDecoder_Open(filter, &CLSID_CoreAVC, &bih, 0, 0); if(!dshowdec) { ERROR_MSG("Cannot open DirectShow codec!"); return 0; } DS_VideoDecoder_SetDestFmt(dshowdec, 12, IMGFMT_YV12, NULL);// DS_VideoDecoder_SetDestFmt(dshowdec, 16, IMGFMT_YUY2, NULL); DS_VideoDecoder_StartInternal(dshowdec); ERROR_MSG("(ThreadID: %u) init complete", SDL_ThreadID());#ifdef DEBUG // Frame counter, only for reference int frames = 0;#endif // Renderer and target surface info Renderer * renderer; Frame frame;#if (C_HAVE_WXGUI) frameSize = 0; frameStartTicks = SDL_GetTicks();#endif while(ThreadRun()) { renderer = (Renderer*)filterinfo; // Get next packet from the fifo queue unsigned int offset; dsinfo.size = fifo->GetPacket(&offset, &dsinfo.frame_pts); if((dsinfo.size == 0) || (dsinfo.size > buffersize)) { LOG_MSG("Error invalid packet size: %d", dsinfo.size); SDL_Delay(10); continue; }#if (C_HAVE_WXGUI) frameSize += dsinfo.size;#endif LockBuffer(); roffset = offset; if(!SDL_SemValue(data)) SDL_SemPost(data); UnlockBuffer(); // Search for SEQ packets (NAL unit type: 0x7) h264info info; if((info.offset = h264findnal_type(buffer+offset, dsinfo.size, 0x07)) > 0) { LOG_MSG("Found SEQ packet, offset %d (0x%x)", info.offset, info.offset); info.pkt = buffer+offset; info.size = dsinfo.size; h264parse_seq(&info); if((w != info.width) || (h != info.height)) { w = info.width; h = info.height; ERROR_MSG("New picture size: %dx%d, time: %.2f", info.width, info.height, info.frame_time); // Setup new size bih.biWidth = w; bih.biHeight = h; DS_VideoDecoder_SetDestFmt(dshowdec, 12, IMGFMT_YV12, &bih); //DS_VideoDecoder_SetDestFmt(dshowdec, 16, IMGFMT_YUY2, &bih); frame.changed = true; } if((info.aspect != 0.0) && (aspect != ((w&0xFFFFFFE0) * info.aspect) / h)) { aspect = ((w&0xFFFFFFE0) * info.aspect) / h; frame.changed = true; LOG_MSG("AR changed to %.2f", aspect); } if(info.frame_time != 0.0) time = info.frame_time;#if (C_HAVE_WXGUI) // New frame size if((frame.changed) && (gui.wxStreamInfo != NULL)) { gui.wxStreamInfo->UpdateVideoStream(w, h, -1, aspect); frameSize = 0; frameStartTicks = SDL_GetTicks(); }#endif } if((w == 0) || (h == 0)) continue; frame.time = time; frame.aspect = aspect; // Lock image surface and write the data if(renderer) { frame.pitch = frame.w = ALIGN(w, 16); frame.h = ALIGN(h, 16); renderer->LockData(&frame); if(frame.id < 0) continue; dsinfo.out_ptr = frame.data[0]; if(!dsinfo.out_ptr) { ERROR_MSG("Error getting image pointer!"); SDL_Delay(10); continue; } dsinfo.in_ptr = buffer+offset; LOG_MSG("Writing to location 0x%x", dsinfo.out_ptr); dsinfo.size = DS_VideoDecoder_DecodeInternal(dshowdec, 1, &dsinfo); if(dsinfo.size > 0) { // We didn't have correct PTS until now frame.pts = dsinfo.frame_pts; renderer->UnlockData(frame.id, &frame); renderer->ReleaseData(frame.id); LOG_MSG("Got %d bytes, PTS: %u", dsinfo.size, dsinfo.frame_pts); frame.changed = false;#if (C_HAVE_WXGUI) Uint32 frameTimeTaken = SDL_GetTicks() - frameStartTicks; // Update ~twice per second if(frameTimeTaken > 500) { if(gui.wxStreamInfo != NULL) gui.wxStreamInfo->UpdateVideoActualBitrate((long)((double)frameSize * 8000.0 / (double)frameTimeTaken)); frameSize = 0; frameStartTicks = SDL_GetTicks(); }#endif#ifdef DEBUG ++frames;#endif } else { LOG_MSG("Error or no data returned!"); renderer->UnlockData(frame.id, NULL); } } } DS_VideoDecoder_StopInternal(dshowdec); DS_VideoDecoder_Destroy(dshowdec); if(renderer) renderer->FlushBuffers(); ERROR_MSG("(ThreadID: %u) finish complete", SDL_ThreadID()); return 0;}#endif // (C_HAS_DIRECTSHOW)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -