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

📄 ds_videodecoder.c

📁 linux下实现视频播放的播放器
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************************	DirectShow Video decoder implementation	Copyright 2000 Eugene Kuznetsov  (divx@euro.ru)*********************************************************/#include "config.h"#if (C_HAS_DIRECTSHOW)#include "guids.h"#include "interfaces.h"#include "registry.h"#ifndef NOAVIFILE_HEADERS#include "videodecoder.h"#else#include "libwin32.h"#endif#include "DS_Filter.h"struct _DS_VideoDecoder{    IVideoDecoder iv;    DS_Filter* m_pDS_Filter;    AM_MEDIA_TYPE m_sOurType, m_sDestType;    VIDEOINFOHEADER* m_sVhdr;    VIDEOINFOHEADER* m_sVhdr2;    int m_Caps;//CAPS m_Caps;                // capabilities of DirectShow decoder    int m_iLastQuality;         // remember last quality as integer    int m_iMinBuffers;    int m_iMaxAuto;    int m_bIsDivX;             // for speed    int m_bIsDivX4;            // for speed};static SampleProcUserData sampleProcData;#include "DS_VideoDecoder.h"#include "wine/winerror.h"#ifdef WIN32_LOADER#include "../ldt_keeper.h"#endif#ifndef NOAVIFILE_HEADERS#define VFW_E_NOT_RUNNING               0x80040226#include "fourcc.h"#include "except.h"#endif#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <sys/types.h>#ifndef __MINGW32__#include <sys/mman.h>#endif// strcmp((const char*)info.dll,...)  is used instead of  (... == ...)// so Arpi could use char* pointer in his simplified DS_VideoDecoder class#define false 0#define true 1int DS_VideoDecoder_GetCapabilities(DS_VideoDecoder *this){    return this->m_Caps;}typedef struct _ct ct;struct _ct {    unsigned int bits;    fourcc_t fcc;    const GUID *subtype;    int cap;};static ct check[] = {	{16, fccYUY2, &MEDIASUBTYPE_YUY2, CAP_YUY2},	{12, fccIYUV, &MEDIASUBTYPE_IYUV, CAP_IYUV},	{16, fccUYVY, &MEDIASUBTYPE_UYVY, CAP_UYVY},	{12, fccYV12, &MEDIASUBTYPE_YV12, CAP_YV12},	//{16, fccYV12, &MEDIASUBTYPE_YV12, CAP_YV12},	{16, fccYVYU, &MEDIASUBTYPE_YVYU, CAP_YVYU},	{12, fccI420, &MEDIASUBTYPE_I420, CAP_I420},	{9,  fccYVU9, &MEDIASUBTYPE_YVU9, CAP_YVU9},	{0, 0, 0, 0},};DWORD avc_quant(BYTE *src, BYTE *dst, int len){    //Stolen from libavcodec h264.c    BYTE *p = src, *d = dst;    int cnt;    cnt = *(p+5) & 0x1f; // Number of sps    if(src[0] != 0x01 || cnt > 1) {	memcpy(dst, src, len);	return len;    }    p += 6;    //cnt > 1 not supported?    cnt = (*p << 8) | *(p+1) + 2;    memcpy(d, p, cnt);    d+=cnt;    p+=cnt;    //assume pps cnt == 1 too    p++;    cnt = (*p << 8) | *(p+1) + 2;    memcpy(d, p, cnt);    return d + cnt - dst;}#define is_avc(cc) (cc == mmioFOURCC('A', 'V', 'C', '1') || \                    cc == mmioFOURCC('a', 'v', 'c', '1'))char *ConvertVIHtoMPEG2VI(VIDEOINFOHEADER *vih, int *size){    struct VIDEOINFOHEADER2 {        RECT32              rcSource;        RECT32              rcTarget;        DWORD               dwBitRate;        DWORD               dwBitErrorRate;        REFERENCE_TIME      AvgTimePerFrame;        DWORD               dwInterlaceFlags;        DWORD               dwCopyProtectFlags;        DWORD               dwPictAspectRatioX;        DWORD               dwPictAspectRatioY;        union {            DWORD           dwControlFlags;            DWORD           dwReserved1;        };        DWORD               dwReserved2;        BITMAPINFOHEADER    bmiHeader;    };    struct MPEG2VIDEOINFO {        struct VIDEOINFOHEADER2    hdr;        DWORD               dwStartTimeCode;        DWORD               cbSequenceHeader;        DWORD               dwProfile;        DWORD               dwLevel;        DWORD               dwFlags;        DWORD               dwSequenceHeader[1];    } *mp2vi;    int extra = 0;    if(vih->bmiHeader.biSize > sizeof(BITMAPINFOHEADER)) {	extra = vih->bmiHeader.biSize-sizeof(BITMAPINFOHEADER);    }    mp2vi = (struct MPEG2VIDEOINFO *)malloc(sizeof(struct MPEG2VIDEOINFO)+extra-4);    memset(mp2vi, 0, sizeof(struct MPEG2VIDEOINFO));    mp2vi->hdr.rcSource = vih->rcSource;    mp2vi->hdr.rcTarget = vih->rcTarget;    mp2vi->hdr.dwBitRate = vih->dwBitRate;    mp2vi->hdr.dwBitErrorRate = vih->dwBitErrorRate;    mp2vi->hdr.AvgTimePerFrame = vih->AvgTimePerFrame;    mp2vi->hdr.dwPictAspectRatioX = vih->bmiHeader.biWidth;    mp2vi->hdr.dwPictAspectRatioY = vih->bmiHeader.biHeight;    memcpy(&mp2vi->hdr.bmiHeader, &vih->bmiHeader, sizeof(BITMAPINFOHEADER));    mp2vi->hdr.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);    if(extra) {	if(is_avc(vih->bmiHeader.biCompression)) {	    mp2vi->dwFlags = 4; //What does this mean?	    mp2vi->cbSequenceHeader = avc_quant(		(BYTE *)(&vih->bmiHeader) + sizeof(BITMAPINFOHEADER),		(BYTE *)(&mp2vi->dwSequenceHeader[0]), extra);	} else {	    mp2vi->cbSequenceHeader = extra;	    memcpy(&mp2vi->dwSequenceHeader[0],		(BYTE *)(&vih->bmiHeader) + sizeof(BITMAPINFOHEADER), extra);	}    }    // The '4' is from the allocated space of dwSequenceHeader    *size = sizeof(struct MPEG2VIDEOINFO) + mp2vi->cbSequenceHeader - 4;    return (char *)mp2vi;}DS_VideoDecoder * DS_VideoDecoder_Open(const char* dllname, GUID* guid, BITMAPINFOHEADER * format, int flip, int maxauto){    DS_VideoDecoder *this;    HRESULT result;    ct* c;    this = malloc(sizeof(DS_VideoDecoder));    memset( this, 0, sizeof(DS_VideoDecoder));    this->m_sVhdr2 = 0;    this->m_iLastQuality = -1;    this->m_iMaxAuto = maxauto;#ifdef WIN32_LOADER    Setup_LDT_Keeper();#endif    //memset(&m_obh, 0, sizeof(m_obh));    //m_obh.biSize = sizeof(m_obh);    {        unsigned int bihs;	bihs = (format->biSize < (int) sizeof(BITMAPINFOHEADER)) ?	    sizeof(BITMAPINFOHEADER) : format->biSize;        this->iv.m_bh = malloc(bihs);        memcpy(this->iv.m_bh, format, bihs);        this->iv.m_bh->biSize = bihs;        this->iv.m_State = STOP;        //this->iv.m_pFrame = 0;        this->iv.m_Mode = DIRECT;        this->iv.m_iDecpos = 0;        this->iv.m_iPlaypos = -1;        this->iv.m_fQuality = 0.0f;        this->iv.m_bCapable16b = true;        bihs += sizeof(VIDEOINFOHEADER) - sizeof(BITMAPINFOHEADER);	this->m_sVhdr = malloc(bihs);	memset(this->m_sVhdr, 0, bihs);	memcpy(&this->m_sVhdr->bmiHeader, this->iv.m_bh, this->iv.m_bh->biSize);	this->m_sVhdr->rcSource.left = this->m_sVhdr->rcSource.top = 0;	this->m_sVhdr->rcSource.right = this->m_sVhdr->bmiHeader.biWidth;	this->m_sVhdr->rcSource.bottom = this->m_sVhdr->bmiHeader.biHeight;	//this->m_sVhdr->rcSource.right = 0;	//this->m_sVhdr->rcSource.bottom = 0;	this->m_sVhdr->rcTarget = this->m_sVhdr->rcSource;	this->m_sOurType.majortype = MEDIATYPE_Video;	this->m_sOurType.subtype = MEDIATYPE_Video;        this->m_sOurType.subtype.f1 = this->m_sVhdr->bmiHeader.biCompression;//	this->m_sOurType.formattype = FORMAT_VideoInfo;	this->m_sOurType.formattype = FORMAT_MPEG2Video;        this->m_sOurType.bFixedSizeSamples = false;	this->m_sOurType.bTemporalCompression = true;	this->m_sOurType.pUnk = 0;        this->m_sOurType.cbFormat = bihs;        this->m_sOurType.pbFormat = (char*)this->m_sVhdr;        if(is_avc(this->m_sVhdr->bmiHeader.biCompression)) {	    int size;	    this->m_sOurType.formattype = FORMAT_MPEG2Video;	    this->m_sOurType.pbFormat =		(char*)ConvertVIHtoMPEG2VI(this->m_sVhdr, &size);	    this->m_sOurType.cbFormat = size;	}	this->m_sVhdr2 = (VIDEOINFOHEADER*)(malloc(sizeof(VIDEOINFOHEADER)+12));	memcpy(this->m_sVhdr2, this->m_sVhdr, sizeof(VIDEOINFOHEADER));        memset((char*)this->m_sVhdr2 + sizeof(VIDEOINFOHEADER), 0, 12);	this->m_sVhdr2->bmiHeader.biCompression = fccYV12;	this->m_sVhdr2->bmiHeader.biBitCount = 24;	memset(&this->m_sDestType, 0, sizeof(this->m_sDestType));	this->m_sDestType.majortype = MEDIATYPE_Video;//	this->m_sDestType.subtype = MEDIASUBTYPE_RGB24;	this->m_sDestType.subtype = MEDIASUBTYPE_YV12;	this->m_sDestType.formattype = FORMAT_VideoInfo;	this->m_sDestType.bFixedSizeSamples = true;	this->m_sDestType.bTemporalCompression = false;	this->m_sDestType.lSampleSize = labs(this->m_sVhdr2->bmiHeader.biWidth*this->m_sVhdr2->bmiHeader.biHeight				       * ((this->m_sVhdr2->bmiHeader.biBitCount + 7) / 8));	this->m_sVhdr2->bmiHeader.biSizeImage = this->m_sDestType.lSampleSize;	this->m_sDestType.pUnk = 0;	this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER);	this->m_sDestType.pbFormat = (char*)this->m_sVhdr2;        memset(&this->iv.m_obh, 0, sizeof(this->iv.m_obh));	memcpy(&this->iv.m_obh, this->iv.m_bh, sizeof(this->iv.m_obh) < (unsigned) this->iv.m_bh->biSize	       ? sizeof(this->iv.m_obh) : (unsigned) this->iv.m_bh->biSize);	this->iv.m_obh.biBitCount=24;        this->iv.m_obh.biSize = sizeof(BITMAPINFOHEADER);        this->iv.m_obh.biCompression = 0;	//BI_RGB        //this->iv.m_obh.biHeight = labs(this->iv.m_obh.biHeight);        this->iv.m_obh.biSizeImage = labs(this->iv.m_obh.biWidth * this->iv.m_obh.biHeight)                              * ((this->iv.m_obh.biBitCount + 7) / 8);	this->m_pDS_Filter = DS_FilterCreate(dllname, guid, &this->m_sOurType, &this->m_sDestType, &sampleProcData);	if (!this->m_pDS_Filter)	{	    ERROR_MSG("Failed to create DirectShow filter");	    return 0;	}	if (!flip)	{	    this->iv.m_obh.biHeight *= -1;	    this->m_sVhdr2->bmiHeader.biHeight = this->iv.m_obh.biHeight;	    result = this->m_pDS_Filter->m_pOutputPin->vt->QueryAccept(this->m_pDS_Filter->m_pOutputPin, &this->m_sDestType);	    if (result)	    {		LOG_MSG("Decoder does not support upside-down RGB frames");		this->iv.m_obh.biHeight *= -1;		this->m_sVhdr2->bmiHeader.biHeight = this->iv.m_obh.biHeight;	    }	}        memcpy( &this->iv.m_decoder, &this->iv.m_obh, sizeof(this->iv.m_obh) );	switch (this->iv.m_bh->biCompression)	{#if 0	case fccDIV3:	case fccDIV4:	case fccDIV5:	case fccDIV6:	case fccMP42:	case fccWMV2:	    //YV12 seems to be broken for DivX :-) codec//	case fccIV50:	    //produces incorrect picture	    //m_Caps = (CAPS) (m_Caps & ~CAP_YV12);	    //m_Caps = CAP_UYVY;//CAP_YUY2; // | CAP_I420;	    //m_Caps = CAP_I420;	    this->m_Caps = (CAP_YUY2 | CAP_UYVY);	    break;#endif	default:	    this->m_Caps = CAP_NONE;	    LOG_MSG("Decoder supports the following YUV formats:");	    for (c = check; c->bits; c++)	    {		this->m_sVhdr2->bmiHeader.biBitCount = c->bits;		this->m_sVhdr2->bmiHeader.biCompression = c->fcc;		this->m_sDestType.subtype = *c->subtype;		result = this->m_pDS_Filter->m_pOutputPin->vt->QueryAccept(this->m_pDS_Filter->m_pOutputPin, &this->m_sDestType);		if (!result)		{		    this->m_Caps = (this->m_Caps | c->cap);		    LOG_MSG("%.4s", (char *)&c->fcc);		}	    }	}	if (this->m_Caps != CAP_NONE) {	    LOG_MSG("Decoder is capable of YUV output (flags 0x%x)", (int)this->m_Caps);	}	this->m_sVhdr2->bmiHeader.biBitCount = 24;	this->m_sVhdr2->bmiHeader.biCompression = 0;	this->m_sDestType.subtype = MEDIASUBTYPE_RGB24;	this->m_iMinBuffers = this->iv.VBUFSIZE;	this->m_bIsDivX = (strcmp(dllname, "divxcvki.ax") == 0		     || strcmp(dllname, "divx_c32.ax") == 0		     || strcmp(dllname, "wmvds32.ax") == 0		     || strcmp(dllname, "wmv8ds32.ax") == 0);	this->m_bIsDivX4 = (strcmp(dllname, "divxdec.ax") == 0);	if (this->m_bIsDivX)	    this->iv.VBUFSIZE += 7;	else if (this->m_bIsDivX4)	    this->iv.VBUFSIZE += 9;    }    ERROR_MSG("Successfully opened %s", dllname);    return this;}void DS_VideoDecoder_Destroy(DS_VideoDecoder *this){    DS_VideoDecoder_StopInternal(this);    this->iv.m_State = STOP;    free(this->m_sVhdr);    free(this->m_sVhdr2);    DS_Filter_Destroy(this->m_pDS_Filter);    ERROR_MSG("Destroyed filter");}void DS_VideoDecoder_StartInternal(DS_VideoDecoder *this){    LOG_MSG("DS_VideoDecoder_StartInternal");    //cout << "DSSTART" << endl;    this->m_pDS_Filter->m_pAll->vt->Commit(this->m_pDS_Filter->m_pAll);    this->m_pDS_Filter->Start(this->m_pDS_Filter);    this->iv.m_State = START;}void DS_VideoDecoder_StopInternal(DS_VideoDecoder *this){#ifdef WIN32_LOADER    Setup_LDT_Keeper(); //prevent a segmentation fault during cleanup#endif    this->m_pDS_Filter->Stop(this->m_pDS_Filter);    //??? why was this here ??? m_pOurOutput->SetFramePointer(0);}int DS_VideoDecoder_DecodeInternal(DS_VideoDecoder *this, int is_keyframe, SampleProcUserData* pUserData){    IMediaSample* sample = 0;    CMediaSample* cs = 0;    COutputPin* out = this->m_pDS_Filter->m_pOurOutput;    char* ptr;    int result;    LONGLONG time_start;    LOG_MSG("DS_VideoDecoder_DecodeInternal(%p,%d,%p,(%d))",this,is_keyframe,pUserData,pUserData->size);    this->m_pDS_Filter->m_pAll->vt->GetBuffer(this->m_pDS_Filter->m_pAll, &sample, 0, 0, 0);    cs = (CMediaSample*)sample;    if (!sample)    {	LOG_MSG("ERROR: null sample");	return -1;    }    // input data    sample->vt->SetActualDataLength(sample, pUserData->size);    cs->SetPointer(cs, pUserData->in_ptr);    sample->vt->SetSyncPoint(sample, is_keyframe);    sample->vt->SetPreroll(sample, pUserData->out_ptr ? 0 : 1);    sampleProcData.size = 0;    time_start = pUserData->frame_pts;    sample->vt->SetTime(sample, &time_start, NULL);    // sample->vt->SetMediaType(sample, &m_sOurType);    // FIXME: - crashing with YV12 at this place decoder will crash    //          while doing this call    // %FS register was not setup for calling into win32 dll. Are all    // crashes inside ...->Receive() fixed now?    //    // nope - but this is surely helpfull - I'll try some more experiments#ifdef WIN32_LOADER    Setup_FS_Segment();#endif    // Set decode buffer    out->SetBuffer(out, pUserData->out_ptr);    LOG_MSG("DS_VideoDecoder_DecodeInternal:Calling codec receive");    result = this->m_pDS_Filter->m_pImp->vt->Receive(this->m_pDS_Filter->m_pImp, sample);

⌨️ 快捷键说明

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