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

📄 xvid_dec.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005  *					All rights reserved * *  This file is part of GPAC / codec pack module * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC 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 Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include <gpac/modules/codec.h>#include <gpac/avparse.h>#include <gpac/constants.h>#include "xvid.h"#ifndef XVID_DEC_FRAME#define XVID_DEC_FRAME xvid_dec_frame_t#define XVID_DEC_PARAM xvid_dec_create_t#else#define XVID_USE_OLD_API#endif#undef XVID_USE_OLD_APIstatic Bool xvid_is_init = 0;typedef struct{	void *codec;	/*no support for scalability in XVID yet*/	u16 ES_ID;	u32 width, height, out_size, pixel_ar;	Bool first_frame;	s32 base_filters;	Float FPS;} XVIDDec;#define XVIDCTX()	XVIDDec *ctx = (XVIDDec *) ifcg->privateStackstatic GF_Err XVID_AttachStream(GF_BaseDecoder *ifcg, u16 ES_ID, char *decSpecInfo, u32 decSpecInfoSize, u16 DependsOnES_ID, u32 objectTypeIndication, Bool UpStream){	GF_M4VDecSpecInfo dsi;	GF_Err e;#ifdef XVID_USE_OLD_API	XVID_DEC_FRAME frame;	XVID_DEC_PARAM par;#else	xvid_dec_frame_t frame;	xvid_dec_create_t par;#endif		XVIDCTX();	if (ctx->ES_ID && ctx->ES_ID!=ES_ID) return GF_NOT_SUPPORTED;	if (!decSpecInfoSize || !decSpecInfo) return GF_NON_COMPLIANT_BITSTREAM;	if (ctx->codec) xvid_decore(ctx->codec, XVID_DEC_DESTROY, NULL, NULL);	/*decode DSI*/	e = gf_m4v_get_config(decSpecInfo, decSpecInfoSize, &dsi);	if (e) return e;	if (!dsi.width || !dsi.height) return GF_NON_COMPLIANT_BITSTREAM;	memset(&par, 0, sizeof(par));	par.width = dsi.width;	par.height = dsi.height;	/*note that this may be irrelevant when used through systems (FPS is driven by systems CTS)*/	ctx->FPS = dsi.clock_rate;	ctx->FPS /= 1000;	if (!ctx->FPS) ctx->FPS = 30.0f;	ctx->pixel_ar = (dsi.par_num<<16) | dsi.par_den;#ifndef XVID_USE_OLD_API	par.version = XVID_VERSION;#endif	if (xvid_decore(NULL, XVID_DEC_CREATE, &par, NULL) < 0) return GF_NON_COMPLIANT_BITSTREAM;	ctx->width = par.width;	ctx->height = par.height;	ctx->codec = par.handle;	/*init decoder*/	memset(&frame, 0, sizeof(frame));	frame.bitstream = (void *) decSpecInfo;	frame.length = decSpecInfoSize;#ifndef XVID_USE_OLD_API	frame.version = XVID_VERSION;	xvid_decore(ctx->codec, XVID_DEC_DECODE, &frame, NULL);#else	/*don't perform error check, XviD doesn't like DSI only frame ...*/	xvid_decore(ctx->codec, XVID_DEC_DECODE, &frame, NULL);#endif	ctx->ES_ID = ES_ID;	ctx->first_frame = 1;	/*output in YV12 only - let the player handle conversion*/	ctx->out_size = ctx->width * ctx->height * 3 / 2;	return GF_OK;}static GF_Err XVID_DetachStream(GF_BaseDecoder *ifcg, u16 ES_ID){	XVIDCTX();	if (ctx->ES_ID != ES_ID) return GF_BAD_PARAM;	if (ctx->codec) xvid_decore(ctx->codec, XVID_DEC_DESTROY, NULL, NULL);	ctx->codec = NULL;	ctx->ES_ID = 0;	ctx->width = ctx->height = ctx->out_size = 0;	return GF_OK;}static GF_Err XVID_GetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability *capability){	XVIDCTX();	switch (capability->CapCode) {	case GF_CODEC_WIDTH:		capability->cap.valueInt = ctx->width;		break;	case GF_CODEC_HEIGHT:		capability->cap.valueInt = ctx->height;		break;	case GF_CODEC_STRIDE:		capability->cap.valueInt = ctx->width;		break;	case GF_CODEC_FPS:		capability->cap.valueFloat = ctx->FPS;		break;	case GF_CODEC_PAR:		capability->cap.valueInt = ctx->pixel_ar;		break;	case GF_CODEC_OUTPUT_SIZE:		capability->cap.valueInt = ctx->out_size;		break;	case GF_CODEC_PIXEL_FORMAT:		capability->cap.valueInt = GF_PIXEL_YV12;		break;	case GF_CODEC_BUFFER_MIN:		capability->cap.valueInt = 1;		break;	case GF_CODEC_BUFFER_MAX:		capability->cap.valueInt = 4;		break;	/*by default we use 4 bytes padding (otherwise it happens that XviD crashes on some videos...)*/	case GF_CODEC_PADDING_BYTES:		capability->cap.valueInt = 32;		break;	/*XviD performs frame reordering internally*/	case GF_CODEC_REORDER:		capability->cap.valueInt = 1;		break;	case GF_CODEC_WANTS_THREAD:	{		const char *sOpt = gf_modules_get_option((GF_BaseInterface *)ifcg, "XviD", "Threaded");		capability->cap.valueInt = (sOpt && stricmp(sOpt, "yes")) ? 1 : 0;	}		break;	/*not known at our level...*/	case GF_CODEC_CU_DURATION:	default:		capability->cap.valueInt = 0;		break;	}	return GF_OK;}static GF_Err XVID_SetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability capability){	/*return unsupported to avoid confusion by the player (like color space changing ...) */	return GF_NOT_SUPPORTED;}static GF_Err XVID_ProcessData(GF_MediaDecoder *ifcg, 		char *inBuffer, u32 inBufferLength,		u16 ES_ID,		char *outBuffer, u32 *outBufferLength,		u8 PaddingBits, u32 mmlevel){#ifdef XVID_USE_OLD_API	XVID_DEC_FRAME frame;#else	xvid_dec_frame_t frame;#endif	s32 postproc;	XVIDCTX();	/*check not using scalabilty*/	if (ES_ID != ctx->ES_ID) return GF_BAD_PARAM;	if (*outBufferLength < ctx->out_size) {		*outBufferLength = ctx->out_size;		return GF_BUFFER_TOO_SMALL;	}	memset(&frame, 0, sizeof(frame));	frame.bitstream = (void *) inBuffer;	frame.length = inBufferLength;#ifdef XVID_USE_OLD_API	frame.colorspace = XVID_CSP_I420;	frame.stride = ctx->width;	frame.image = (void *) outBuffer;#else	frame.version = XVID_VERSION;	frame.output.csp = XVID_CSP_I420;	frame.output.stride[0] = ctx->width;	frame.output.plane[0] = (void *) outBuffer;#endif	/*to check, not convinced yet by results...*/	postproc = ctx->base_filters;	switch (mmlevel) {	case GF_CODEC_LEVEL_SEEK:	case GF_CODEC_LEVEL_DROP:		/*turn off all post-proc*/#ifdef XVID_USE_OLD_API		postproc &= ~XVID_DEC_DEBLOCKY;		postproc &= ~XVID_DEC_DEBLOCKUV;#else		postproc &= ~XVID_DEBLOCKY;		postproc &= ~XVID_DEBLOCKUV;		postproc &= ~XVID_FILMEFFECT;#endif		break;	case GF_CODEC_LEVEL_VERY_LATE:		/*turn off post-proc*/#ifdef XVID_USE_OLD_API		postproc &= ~XVID_DEC_DEBLOCKY;#else		postproc &= ~XVID_FILMEFFECT;		postproc &= ~XVID_DEBLOCKY;#endif		break;	case GF_CODEC_LEVEL_LATE:#ifdef XVID_USE_OLD_API		postproc &= ~XVID_DEC_DEBLOCKUV;#else		postproc &= ~XVID_DEBLOCKUV;		postproc &= ~XVID_FILMEFFECT;#endif		break;	}	postproc = 0;	/*xvid is a real pain here, it may keep the first I frame and force a 1-frame delay, so we simply	trick it*/	if (ctx->first_frame) { outBuffer[0] = 'v'; outBuffer[1] = 'o'; outBuffer[2] = 'i'; outBuffer[3] = 'd'; }	if (xvid_decore(ctx->codec, XVID_DEC_DECODE, &frame, NULL) < 0) {		*outBufferLength = 0;		return GF_NON_COMPLIANT_BITSTREAM;	}	/*dispatch nothing if seeking or droping*/	switch (mmlevel) {	case GF_CODEC_LEVEL_SEEK:	case GF_CODEC_LEVEL_DROP:		*outBufferLength = 0;		break;	default:		*outBufferLength = ctx->out_size;		if (ctx->first_frame) {			ctx->first_frame = 0;			if ((outBuffer[0] == 'v') && (outBuffer[1] == 'o') && (outBuffer[2] == 'i') && (outBuffer[3] == 'd'))				*outBufferLength = 0;		}		break;	}	return GF_OK;}static Bool XVID_CanHandleStream(GF_BaseDecoder *dec, u32 StreamType, u32 ObjectType, char *decSpecInfo, u32 decSpecInfoSize, u32 PL){	if (StreamType != GF_STREAM_VISUAL) return 0;	switch (ObjectType) {	case 0x20:		return 1;	/*cap query*/	case 0:		return 1;	}	return 0;}static const char *XVID_GetCodecName(GF_BaseDecoder *dec){#ifdef XVID_USE_OLD_API	return "XviD Dev Version";#else	return "XviD 1.0";#endif}GF_BaseDecoder *NewXVIDDec(){	const char *sOpt;	GF_MediaDecoder *ifcd;	XVIDDec *dec;		GF_SAFEALLOC(ifcd, GF_MediaDecoder);	GF_SAFEALLOC(dec, XVIDDec);	GF_REGISTER_MODULE_INTERFACE(ifcd, GF_MEDIA_DECODER_INTERFACE, "XviD Decoder", "gpac distribution")	ifcd->privateStack = dec;	if (!xvid_is_init) {#ifdef XVID_USE_OLD_API		XVID_INIT_PARAM init;		init.api_version = 0;		init.core_build = 0;		/*get info*/		init.cpu_flags = XVID_CPU_CHKONLY;		xvid_init(NULL, 0, &init, NULL);		/*then init*/		xvid_init(NULL, 0, &init, NULL);#else		xvid_gbl_init_t init;		init.debug = 0;		init.version = XVID_VERSION;		init.cpu_flags = 0; /*autodetect*/		xvid_global(NULL, 0, &init, NULL);#endif		xvid_is_init = 1;	}	/*get config*/	dec->base_filters = 0;	sOpt = gf_modules_get_option((GF_BaseInterface *)ifcd, "XviD", "PostProc");	if (sOpt) {#ifndef XVID_USE_OLD_API		if (strstr(sOpt, "FilmEffect")) dec->base_filters |= XVID_FILMEFFECT;#endif		if (strstr(sOpt, "Deblock_Y")) {#ifdef XVID_USE_OLD_API			dec->base_filters |= XVID_DEC_DEBLOCKY;#else			dec->base_filters |= XVID_DEBLOCKY;#endif		}		if (strstr(sOpt, "Deblock_UV")) {#ifdef XVID_USE_OLD_API			dec->base_filters |= XVID_DEC_DEBLOCKUV;#else			dec->base_filters |= XVID_DEBLOCKUV;#endif		}	}	/*setup our own interface*/		ifcd->AttachStream = XVID_AttachStream;	ifcd->DetachStream = XVID_DetachStream;	ifcd->GetCapabilities = XVID_GetCapabilities;	ifcd->SetCapabilities = XVID_SetCapabilities;	ifcd->GetName = XVID_GetCodecName;	ifcd->CanHandleStream = XVID_CanHandleStream;	ifcd->ProcessData = XVID_ProcessData;	return (GF_BaseDecoder *) ifcd;}void DeleteXVIDDec(GF_BaseDecoder *ifcg){	XVIDCTX();	if (ctx->codec) xvid_decore(ctx->codec, XVID_DEC_DESTROY, NULL, NULL);	free(ctx);	free(ifcg);}Bool QueryInterface(u32 InterfaceType) {	if (InterfaceType == GF_MEDIA_DECODER_INTERFACE) return 1;	return 0;}GF_BaseInterface *LoadInterface(u32 InterfaceType) {	if (InterfaceType == GF_MEDIA_DECODER_INTERFACE) return (GF_BaseInterface *)NewXVIDDec();	return NULL;}void ShutdownInterface(GF_BaseInterface *ifce){	switch (ifce->InterfaceType) {	case GF_MEDIA_DECODER_INTERFACE: 		DeleteXVIDDec((GF_BaseDecoder*)ifce);		break;	}}

⌨️ 快捷键说明

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