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

📄 ffmpeg_decode.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005 *					All rights reserved * *  This file is part of GPAC / FFMPEG 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 "ffmpeg_in.h"#include <gpac/avparse.h>static void gf_av_vlog(void* avcl, int level, const char *fmt, va_list vl){	char szMsg[1024];	vsprintf(szMsg, fmt, vl);	GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, (szMsg));}static AVCodec *ffmpeg_get_codec(u32 codec_4cc){	char name[5];	AVCodec *codec;	strcpy(name, gf_4cc_to_str(codec_4cc));	codec = avcodec_find_decoder_by_name(name);	if (!codec) {		strupr(name);		codec = avcodec_find_decoder_by_name(name);		if (!codec) {			strlwr(name);			codec = avcodec_find_decoder_by_name(name);		}	}	/*custom mapings*/	if (!codec) {		if (!stricmp(name, "s263")) codec = avcodec_find_decoder_by_name("h263");		else if (!stricmp(name, "samr") || !stricmp(name, "amr ")) codec = avcodec_find_decoder_by_name("amr_nb");		else if (!stricmp(name, "sawb")) codec = avcodec_find_decoder_by_name("amr_wb");	}	return codec;}static void FFDEC_LoadDSI(FFDec *ffd, GF_BitStream *bs, Bool from_ff_demux){	u32 dsi_size;	if (!ffd->codec) return;	dsi_size = (u32) gf_bs_available(bs);	if (!dsi_size) return;	/*demuxer is ffmpeg, extra data can be copied directly*/	if (from_ff_demux) {		free(ffd->ctx->extradata);		ffd->ctx->extradata_size = dsi_size;		ffd->ctx->extradata = (uint8_t*) malloc(sizeof(char)*ffd->ctx->extradata_size);		gf_bs_read_data(bs, ffd->ctx->extradata, ffd->ctx->extradata_size);		return;	}	switch (ffd->codec->id) {	case CODEC_ID_SVQ3:	{		u32 at_type, size;		size = gf_bs_read_u32(bs);		/*there should be an 'SMI' entry*/		at_type = gf_bs_read_u32(bs);		if (at_type == GF_4CC('S', 'M', 'I', ' ')) {			free(ffd->ctx->extradata);			ffd->ctx->extradata_size = 0x5a + size;			ffd->ctx->extradata = (uint8_t*) malloc(sizeof(char)*ffd->ctx->extradata_size);			strcpy(ffd->ctx->extradata, "SVQ3");			gf_bs_read_data(bs, (unsigned char *)ffd->ctx->extradata + 0x5a, size);		}	}		break;	default:		free(ffd->ctx->extradata);		ffd->ctx->extradata_size = dsi_size;		ffd->ctx->extradata = (uint8_t*) malloc(sizeof(char)*ffd->ctx->extradata_size);		gf_bs_read_data(bs, ffd->ctx->extradata, ffd->ctx->extradata_size);		break;	}}static GF_Err FFDEC_AttachStream(GF_BaseDecoder *plug, u16 ES_ID, char *decSpecInfo, u32 decSpecInfoSize, u16 DependsOnES_ID, u32 objectTypeIndication, Bool UpStream){	u32 codec_id;	int gotpic;	GF_BitStream *bs;	GF_M4VDecSpecInfo dsi;	GF_Err e;	FFDec *ffd = (FFDec *)plug->privateStack;	if (ffd->ES_ID || DependsOnES_ID || UpStream) return GF_NOT_SUPPORTED;	if (!ffd->oti) return GF_NOT_SUPPORTED;	ffd->ES_ID = ES_ID;	ffd->ctx = avcodec_alloc_context();		/*private FFMPEG DSI*/	if (ffd->oti == GPAC_FFMPEG_CODECS_OTI) {		bs = gf_bs_new(decSpecInfo, decSpecInfoSize, GF_BITSTREAM_READ);		codec_id = gf_bs_read_u32(bs);		if (ffd->st==GF_STREAM_AUDIO) {			ffd->ctx->codec_type = CODEC_TYPE_AUDIO;			ffd->ctx->sample_rate = gf_bs_read_u32(bs);			ffd->ctx->channels = gf_bs_read_u16(bs);			ffd->ctx->bits_per_sample = gf_bs_read_u16(bs);			/*force 16 bits output*/			ffd->ctx->bits_per_sample = 16;			ffd->ctx->frame_size = gf_bs_read_u16(bs);			ffd->ctx->block_align = gf_bs_read_u16(bs);		} else if (ffd->st==GF_STREAM_VISUAL) {			ffd->ctx->codec_type = CODEC_TYPE_VIDEO;			ffd->ctx->width = gf_bs_read_u32(bs);			ffd->ctx->height = gf_bs_read_u32(bs);		}		ffd->ctx->codec_tag = gf_bs_read_u32(bs);		ffd->ctx->bit_rate = gf_bs_read_u32(bs);		ffd->codec = avcodec_find_decoder(codec_id);		FFDEC_LoadDSI(ffd, bs, 1);		gf_bs_del(bs);	} 	/*private QT DSI*/	else if (ffd->oti == GPAC_EXTRA_CODECS_OTI) {		bs = gf_bs_new(decSpecInfo, decSpecInfoSize, GF_BITSTREAM_READ);		codec_id = gf_bs_read_u32(bs);		if (ffd->st==GF_STREAM_AUDIO) {			ffd->ctx->codec_type = CODEC_TYPE_AUDIO;			ffd->ctx->sample_rate = gf_bs_read_u16(bs);			ffd->ctx->frame_size = gf_bs_read_u16(bs);			ffd->ctx->channels = gf_bs_read_u8(bs);			ffd->ctx->bits_per_sample = gf_bs_read_u8(bs);			/*packed mode*/ gf_bs_read_u8(bs);			/*just in case...*/			if (codec_id == GF_4CC('a', 'm', 'r', ' ')) {			  ffd->ctx->sample_rate = 8000;			  ffd->ctx->channels = 1;			  ffd->ctx->bits_per_sample = 16;			  ffd->ctx->frame_size = 160;			}		} else if (ffd->st==GF_STREAM_VISUAL) {			ffd->ctx->codec_type = CODEC_TYPE_VIDEO;			ffd->ctx->width = gf_bs_read_u16(bs);			ffd->ctx->height = gf_bs_read_u16(bs);		}		ffd->codec = ffmpeg_get_codec(codec_id);		FFDEC_LoadDSI(ffd, bs, 0);		gf_bs_del(bs);	}	/*use std MPEG-4 st/oti*/	else {		u32 codec_id = 0;		if (ffd->st==GF_STREAM_VISUAL) {			ffd->ctx->codec_type = CODEC_TYPE_VIDEO;			switch (ffd->oti) {			case 0x20:				codec_id = CODEC_ID_MPEG4;				break;			case 0x21:				codec_id = CODEC_ID_H264;				/*ffmpeg H264/AVC needs that*/				ffd->ctx->codec_tag = 0x31637661;				break;			case 0x6A:			case 0x60:			case 0x61:			case 0x62:			case 0x63:			case 0x64:			case 0x65:				codec_id = CODEC_ID_MPEG2VIDEO;				break;			case 0x6C:				codec_id = CODEC_ID_MJPEG;				break;			case 0xFF:				codec_id = CODEC_ID_SVQ3;				break;			}		} else if (ffd->st==GF_STREAM_AUDIO) {			ffd->ctx->codec_type = CODEC_TYPE_AUDIO;			switch (ffd->oti) {			case 0x69:			case 0x6B:				ffd->ctx->frame_size = 1152;				codec_id = CODEC_ID_MP2;				break;			}		}		else if ((ffd->st==GF_STREAM_ND_SUBPIC) && (ffd->oti==0xe0)) {			codec_id = CODEC_ID_DVD_SUBTITLE;		}		ffd->codec = avcodec_find_decoder(codec_id);	}	/*should never happen*/	if (!ffd->codec) return GF_OUT_OF_MEM;	/*setup MPEG-4 video streams*/	if ((ffd->st==GF_STREAM_VISUAL)) {		/*for all MPEG-4 variants get size*/		if ((ffd->oti==0x20) || (ffd->oti == 0x21)) {			if (!decSpecInfoSize || !decSpecInfo) return GF_NON_COMPLIANT_BITSTREAM;			/*for regular MPEG-4, try to decode and if this fails try H263 decoder at first frame*/			if (ffd->oti==0x20) {				e = gf_m4v_get_config(decSpecInfo, decSpecInfoSize, &dsi);				if (e) return e;				ffd->ctx->width = dsi.width;				ffd->ctx->height = dsi.height;				if (!dsi.width && !dsi.height) ffd->check_short_header = 1;				ffd->previous_par = (dsi.par_num<<16) | dsi.par_den;				ffd->no_par_update = 1;			} else if (ffd->oti==0x21) {				ffd->check_h264_isma = 1;			}			/*setup dsi for FFMPEG context BEFORE attaching decoder (otherwise not proper init)*/			ffd->ctx->extradata = malloc(sizeof(char)*decSpecInfoSize);			memcpy(ffd->ctx->extradata, decSpecInfo, decSpecInfoSize);			ffd->ctx->extradata_size = decSpecInfoSize;		}		ffd->frame = avcodec_alloc_frame();	}	if (avcodec_open(ffd->ctx, ffd->codec)<0) return GF_NON_COMPLIANT_BITSTREAM;	/*setup audio streams*/	if (ffd->st==GF_STREAM_AUDIO) {		if ((ffd->codec->type == CODEC_ID_MP3LAME) || (ffd->codec->type == CODEC_ID_MP2)) {			ffd->ctx->frame_size = (ffd->ctx->sample_rate > 24000) ? 1152 : 576;		}		/*may be 0 (cfg not known yet)*/		ffd->out_size = ffd->ctx->bits_per_sample * ffd->ctx->channels * ffd->ctx->frame_size / 8;		if (!ffd->ctx->bits_per_sample) ffd->ctx->bits_per_sample = 16;		if (!ffd->ctx->sample_rate) ffd->ctx->sample_rate = 44100;		if (!ffd->ctx->channels) ffd->ctx->channels = 2;	} else {		switch (ffd->codec->id) {		case CODEC_ID_MJPEG:		case CODEC_ID_MJPEGB:		case CODEC_ID_LJPEG:			ffd->pix_fmt = GF_PIXEL_RGB_24; 			break;		case CODEC_ID_DVD_SUBTITLE:			ffd->frame = avcodec_alloc_frame();			avcodec_decode_video(ffd->ctx, ffd->frame, &gotpic, decSpecInfo, decSpecInfoSize);			ffd->pix_fmt = GF_PIXEL_YV12; 			break;		default:			ffd->pix_fmt = GF_PIXEL_YV12; 			break;		}		ffd->out_size = ffd->ctx->width * ffd->ctx->height * 3;		if (ffd->pix_fmt!=GF_PIXEL_RGB_24) ffd->out_size /= 2;	}#if 0	ffd->ctx->debug = FF_DEBUG_PICT_INFO | FF_DEBUG_BITSTREAM | FF_DEBUG_STARTCODE;	ffd->ctx->debug = 0xFFFFFFFF;	av_log_set_level(AV_LOG_DEBUG);	av_log_set_callback(gf_av_vlog);#endif	return GF_OK;}static GF_Err FFDEC_DetachStream(GF_BaseDecoder *plug, u16 ES_ID){	FFDec *ffd = (FFDec *)plug->privateStack;	if (!ffd->ES_ID) return GF_BAD_PARAM;	ffd->ES_ID = 0;	if (ffd->ctx) {		if (ffd->ctx->extradata) free(ffd->ctx->extradata);		avcodec_close(ffd->ctx);		ffd->ctx = NULL;	}	return GF_OK;}static GF_Err FFDEC_GetCapabilities(GF_BaseDecoder *plug, GF_CodecCapability *capability){	FFDec *ffd = (FFDec *)plug->privateStack;	/*base caps*/	switch (capability->CapCode) {	/*ffmpeg seems quite reliable*/	case GF_CODEC_RESILIENT:		capability->cap.valueInt = 1;		return GF_OK;	case GF_CODEC_PADDING_BYTES:		capability->cap.valueInt = FF_INPUT_BUFFER_PADDING_SIZE;		return GF_OK;	case GF_CODEC_REORDER:		capability->cap.valueInt = 1;		return GF_OK;	}	if (!ffd->ctx) {		capability->cap.valueInt = 0;		return GF_OK;	}	/*caps valid only if stream attached*/	switch (capability->CapCode) {	case GF_CODEC_OUTPUT_SIZE:		capability->cap.valueInt = ffd->out_size;		break;	case GF_CODEC_SAMPLERATE:		capability->cap.valueInt = ffd->ctx->sample_rate;		break;	case GF_CODEC_NB_CHAN:		capability->cap.valueInt = ffd->ctx->channels;		break;	case GF_CODEC_BITS_PER_SAMPLE:		capability->cap.valueInt = ffd->ctx->bits_per_sample;		break;	case GF_CODEC_BUFFER_MIN:		capability->cap.valueInt = (ffd->st==GF_STREAM_AUDIO) ? 4 : 1;		break;	case GF_CODEC_BUFFER_MAX:	  /*for audio let the systems engine decide since we may have very large block size (1 sec with some QT movies)*/		capability->cap.valueInt = (ffd->st==GF_STREAM_AUDIO) ? 0 : 4;		break;	/*by default AAC access unit lasts num_samples (timescale being sampleRate)*/	case GF_CODEC_CU_DURATION:		capability->cap.valueInt =  (ffd->st==GF_STREAM_AUDIO) ? ffd->ctx->frame_size : 0;		break;	case GF_CODEC_WIDTH:		capability->cap.valueInt = ffd->ctx->width;		break;	case GF_CODEC_HEIGHT:		capability->cap.valueInt = ffd->ctx->height;		break;	case GF_CODEC_STRIDE:		capability->cap.valueInt = (ffd->pix_fmt==GF_PIXEL_RGB_24) ? ffd->ctx->width*3 : ffd->ctx->width;		break;	case GF_CODEC_FPS:		capability->cap.valueFloat = 30.0f;		break;	case GF_CODEC_PAR:		capability->cap.valueInt = ffd->previous_par;		break;	case GF_CODEC_PIXEL_FORMAT:		if (ffd->ctx->width) {			capability->cap.valueInt = ffd->pix_fmt;		}		break;	/*ffmpeg performs frame reordering internally*/	case GF_CODEC_REORDER:		capability->cap.valueInt = 1;		break;	case GF_CODEC_WAIT_RAP:		//ffd->ctx->hurry_up = 5;		break;	case GF_CODEC_CHANNEL_CONFIG:		/*currently unused in ffmpeg*/		if (ffd->ctx->channels==1) {			capability->cap.valueInt = GF_AUDIO_CH_FRONT_CENTER;		} else {			capability->cap.valueInt = GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT;		}		break;

⌨️ 快捷键说明

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