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

📄 libds_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"#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 + -