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

📄 ffmpeg_decode.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
	default:		capability->cap.valueInt = 0;		break;	}	return GF_OK;}static GF_Err FFDEC_SetCapabilities(GF_BaseDecoder *plug, GF_CodecCapability capability){	FFDec *ffd = (FFDec *)plug->privateStack;	switch (capability.CapCode) {	case GF_CODEC_WAIT_RAP:		ffd->frame_start = 0;		if (ffd->st==GF_STREAM_VISUAL) avcodec_flush_buffers(ffd->ctx);		return GF_OK;	default:		/*return unsupported to avoid confusion by the player (like color space changing ...) */		return GF_NOT_SUPPORTED;	}}static GF_Err FFDEC_ProcessData(GF_MediaDecoder *plug, 		char *inBuffer, u32 inBufferLength,		u16 ES_ID,		char *outBuffer, u32 *outBufferLength,		u8 PaddingBits, u32 mmlevel){	s32 gotpic;	u32 outsize;	FFDec *ffd = plug->privateStack;	/*WARNING: this breaks H264 (and maybe others) decoding, disabled for now*/#if 1	if (!ffd->ctx->hurry_up) {		switch (mmlevel) {		case GF_CODEC_LEVEL_SEEK:		case GF_CODEC_LEVEL_DROP:			/*skip as much as possible*/			ffd->ctx->hurry_up = 5;			break;		case GF_CODEC_LEVEL_VERY_LATE:		case GF_CODEC_LEVEL_LATE:			/*skip B-frames*/			ffd->ctx->hurry_up = 1;			break;		default:			ffd->ctx->hurry_up = 0;			break;		}	}#endif	/*audio stream*/	if (ffd->st==GF_STREAM_AUDIO) {		s32 len;		u32 buf_size = (*outBufferLength);		(*outBufferLength) = 0;		/*seeking don't decode*/		if (!inBuffer || (mmlevel == GF_CODEC_LEVEL_SEEK)) {			*outBufferLength = 0;			ffd->frame_start = 0;			return GF_OK;		}		if (ffd->frame_start>inBufferLength) ffd->frame_start = 0;redecode:		len = avcodec_decode_audio(ffd->ctx, (short *)ffd->audio_buf, &gotpic, inBuffer + ffd->frame_start, inBufferLength - ffd->frame_start);		if (len<0) { ffd->frame_start = 0; return GF_NON_COMPLIANT_BITSTREAM; }		if (gotpic<0) { ffd->frame_start = 0; return GF_OK; }		ffd->ctx->hurry_up = 0;		if (ffd->ctx->frame_size < gotpic) ffd->ctx->frame_size = gotpic;		/*first config*/		if (!ffd->out_size) {			ffd->ctx->bits_per_sample = 16;			ffd->out_size = ffd->ctx->bits_per_sample * ffd->ctx->channels * ffd->ctx->frame_size / 8;		}		if (ffd->out_size < (u32) gotpic) {			ffd->ctx->bits_per_sample = 16;			/*looks like relying on frame_size is not a good idea for all codecs, so we use gotpic*/			(*outBufferLength) = ffd->out_size = gotpic;			return GF_BUFFER_TOO_SMALL;		}		if (ffd->out_size > buf_size) {			/*don't use too small output chunks otherwise we'll never have enough when mixing - we could 			also request more slots in the composition memory but let's not waste mem*/			if (ffd->out_size < (u32) 576*ffd->ctx->channels) ffd->out_size=ffd->ctx->channels*576;			(*outBufferLength) = ffd->out_size;			return GF_BUFFER_TOO_SMALL;		}				/*we're sure to have at least gotpic bytes available in output*/		memcpy(outBuffer, ffd->audio_buf, sizeof(char) * gotpic);		(*outBufferLength) += gotpic;		outBuffer += gotpic;		ffd->frame_start += len;		if (inBufferLength <= ffd->frame_start) {			ffd->frame_start = 0;			return GF_OK;		}		/*still space go on*/		if ((*outBufferLength)+ffd->ctx->frame_size<ffd->out_size) goto redecode;		/*more frames in the current sample*/		return GF_PACKED_FRAMES;	} else {		s32 w = ffd->ctx->width;		s32 h = ffd->ctx->height;		if (ffd->check_h264_isma) {			/*for AVC bitstreams after ISMA decryption, in case (as we do) the decryption DRM tool 			doesn't put back nalu size, do it ourselves...*/			if (inBuffer && !inBuffer[0] && !inBuffer[1] && !inBuffer[2] && (inBuffer[3]==0x01)) {				u32 nalu_size;				u32 remain = inBufferLength;				char *start, *end;				start = inBuffer;				end = inBuffer + 4;				while (remain>4) {					if (!end[0] && !end[1] && !end[2] && (end[3]==0x01)) {						nalu_size = end - start - 4;						start[0] = (nalu_size>>24)&0xFF;						start[1] = (nalu_size>>16)&0xFF;						start[2] = (nalu_size>>8)&0xFF;						start[3] = (nalu_size)&0xFF;						start = end;						end = start+4;						continue;					}					end++;					remain--;				}				nalu_size = end - start - 4;				start[0] = (nalu_size>>24)&0xFF;				start[1] = (nalu_size>>16)&0xFF;				start[2] = (nalu_size>>8)&0xFF;				start[3] = (nalu_size)&0xFF;				ffd->check_h264_isma = 2;			}			/*if we had ISMA E&A and lost it this is likely due to a pck loss - do NOT switch back to regular*/			else if (ffd->check_h264_isma == 1) {				ffd->check_h264_isma = 0;			}		}		if (avcodec_decode_video(ffd->ctx, ffd->frame, &gotpic, inBuffer, inBufferLength) < 0) {			if (!ffd->check_short_header) {				return GF_NON_COMPLIANT_BITSTREAM;			}			/*switch to H263 (ffmpeg MPEG-4 codec doesn't understand short headers)*/			{				u32 old_codec = ffd->codec->id;				ffd->check_short_header = 0;				/*OK we loose the DSI stored in the codec context, but H263 doesn't need any, and if we're				here this means the DSI was broken, so no big deal*/				avcodec_close(ffd->ctx);				ffd->codec = avcodec_find_decoder(CODEC_ID_H263);				if (!ffd->codec || (avcodec_open(ffd->ctx, ffd->codec)<0)) return GF_NON_COMPLIANT_BITSTREAM;				if (avcodec_decode_video(ffd->ctx, ffd->frame, &gotpic, inBuffer, inBufferLength) < 0) {					/*nope, stay in MPEG-4*/					avcodec_close(ffd->ctx);					ffd->codec = avcodec_find_decoder(old_codec);					assert(ffd->codec);					avcodec_open(ffd->ctx, ffd->codec);					return GF_NON_COMPLIANT_BITSTREAM;				}			}		}		ffd->ctx->hurry_up = 0;		/*recompute outsize in case on-the-fly change*/		if ((w != ffd->ctx->width) || (h != ffd->ctx->height)) {			outsize = ffd->ctx->width * ffd->ctx->height * 3;			if (ffd->pix_fmt!=GF_PIXEL_RGB_24) outsize /= 2;			ffd->out_size = outsize;			*outBufferLength = ffd->out_size;			if (ffd->check_h264_isma) {				inBuffer[0] = inBuffer[1] = inBuffer[2] = 0;				inBuffer[3] = 1;			}			return GF_BUFFER_TOO_SMALL;		}		/*check PAR in case on-the-fly change*/		if (!ffd->no_par_update && ffd->ctx->sample_aspect_ratio.num && ffd->ctx->sample_aspect_ratio.den) {			outsize = (ffd->ctx->sample_aspect_ratio.num<<16) | ffd->ctx->sample_aspect_ratio.den;			if (outsize!=ffd->previous_par) {				ffd->previous_par=outsize;				*outBufferLength = ffd->out_size;				return GF_BUFFER_TOO_SMALL;			}		}		*outBufferLength = 0;		if (mmlevel	== GF_CODEC_LEVEL_SEEK) return GF_OK;		if (gotpic) {//#if defined(_WIN32_WCE) ||  defined(__SYMBIAN32__)#if 1			if (ffd->pix_fmt==GF_PIXEL_RGB_24) {				memcpy(outBuffer, ffd->frame->data[0], sizeof(char)*3*ffd->ctx->width);			} else {				s32 i;				char *pYO, *pUO, *pVO;				unsigned char *pYD, *pUD, *pVD;				pYO = ffd->frame->data[0];				pUO = ffd->frame->data[1];				pVO = ffd->frame->data[2];				pYD = outBuffer;				pUD = outBuffer + ffd->ctx->width * ffd->ctx->height;				pVD = outBuffer + 5 * ffd->ctx->width * ffd->ctx->height / 4;								for (i=0; i<ffd->ctx->height; i++) {					memcpy(pYD, pYO, sizeof(char) * ffd->ctx->width);					pYD += ffd->ctx->width;					pYO += ffd->frame->linesize[0];					if (i%2) continue;					memcpy(pUD, pUO, sizeof(char) * ffd->ctx->width/2);					memcpy(pVD, pVO, sizeof(char) * ffd->ctx->width/2);					pUD += ffd->ctx->width/2;					pVD += ffd->ctx->width/2;					pUO += ffd->frame->linesize[1];					pVO += ffd->frame->linesize[2];				}				*outBufferLength = ffd->out_size;			}#else			AVPicture pict;			u32 pix_out;			memset(&pict, 0, sizeof(pict));			if (ffd->pix_fmt==GF_PIXEL_RGB_24) {				pict.data[0] = outBuffer;				pict.linesize[0] = 3*ffd->ctx->width;				pix_out = PIX_FMT_RGB24;			} else {				pict.data[0] = outBuffer;				pict.data[1] = outBuffer + ffd->ctx->width * ffd->ctx->height;				pict.data[2] = outBuffer + 5 * ffd->ctx->width * ffd->ctx->height / 4;				pict.linesize[0] = ffd->ctx->width;				pict.linesize[1] = pict.linesize[2] = ffd->ctx->width/2;				pix_out = PIX_FMT_YUV420P;				if (!mmlevel && ffd->frame->interlaced_frame) {					avpicture_deinterlace((AVPicture *) ffd->frame, (AVPicture *) ffd->frame, ffd->ctx->pix_fmt, ffd->ctx->width, ffd->ctx->height);				}			}			pict.data[3] = 0;			pict.linesize[3] = 0;			img_convert(&pict, pix_out, (AVPicture *) ffd->frame, ffd->ctx->pix_fmt, ffd->ctx->width, ffd->ctx->height);			*outBufferLength = ffd->out_size;#endif		}	}	return GF_OK;}static Bool FFDEC_CanHandleStream(GF_BaseDecoder *plug, u32 StreamType, u32 ObjectType, char *decSpecInfo, u32 decSpecInfoSize, u32 PL){	GF_BitStream *bs;	u32 codec_id;	Bool check_4cc;	FFDec *ffd = plug->privateStack;	if (!ObjectType) {		if ((StreamType==GF_STREAM_VISUAL) || (StreamType==GF_STREAM_AUDIO)) return 1;		return 0;	}	/*store types*/	ffd->oti = ObjectType;	ffd->st = StreamType;	codec_id = 0;	check_4cc = 0;		/*private from FFMPEG input*/	if (ObjectType == GPAC_FFMPEG_CODECS_OTI) {		bs = gf_bs_new(decSpecInfo, decSpecInfoSize, GF_BITSTREAM_READ);		codec_id = gf_bs_read_u32(bs);		gf_bs_del(bs);	}	/*private from IsoMedia input*/	else if (ObjectType == GPAC_EXTRA_CODECS_OTI) {		bs = gf_bs_new(decSpecInfo, decSpecInfoSize, GF_BITSTREAM_READ);		codec_id = gf_bs_read_u32(bs);		check_4cc = 1;		gf_bs_del(bs);	}	/*std MPEG-4 audio*/	else if (StreamType==GF_STREAM_AUDIO) {		if ((ObjectType==0x69) || (ObjectType==0x6B)) codec_id = CODEC_ID_MP2;	} 	/*std MPEG-4 visual*/	else if (StreamType==GF_STREAM_VISUAL) {		switch (ObjectType) {		/*MPEG-4 v1 simple profile*/		case 0x20: codec_id = CODEC_ID_MPEG4; break;		/*H264 (not std OTI, just the way we use it internally)*/		case 0x21: codec_id = CODEC_ID_H264; break;		/*MPEG1 video*/		case 0x6A:		/*MPEG2 video*/		case 0x60:		case 0x61:		case 0x62:		case 0x63:		case 0x64:		case 0x65:			codec_id = CODEC_ID_MPEG2VIDEO; break;		/*JPEG*/		case 0x6C:			return 0; /*I'm having troubles with ffmpeg & jpeg, it appears to crash randomly*/			return 1;		default:			return 0;		}	}	/*NeroDigital DVD subtitles*/	else if ((StreamType==GF_STREAM_ND_SUBPIC) && (ObjectType==0xe0)) 		return 1;	if (!codec_id) return 0;	if (check_4cc && (ffmpeg_get_codec(codec_id) != NULL)) return 1;	if (avcodec_find_decoder(codec_id) != NULL) return 1;	return 0;}static char szCodec[100];static const char *FFDEC_GetCodecName(GF_BaseDecoder *dec){	FFDec *ffd = dec->privateStack;	if (ffd->codec) {		sprintf(szCodec, "FFMPEG %s", ffd->codec->name ? ffd->codec->name : "unknown");		return szCodec;	}	return NULL;}void *FFDEC_Load(){	GF_MediaDecoder *ptr;	FFDec *priv;    avcodec_init();	avcodec_register_all();	GF_SAFEALLOC(ptr , GF_MediaDecoder);	GF_SAFEALLOC(priv , FFDec);	ptr->privateStack = priv;	ptr->AttachStream = FFDEC_AttachStream;	ptr->DetachStream = FFDEC_DetachStream;	ptr->GetCapabilities = FFDEC_GetCapabilities;	ptr->SetCapabilities = FFDEC_SetCapabilities;	ptr->CanHandleStream = FFDEC_CanHandleStream;	ptr->GetName = FFDEC_GetCodecName;	ptr->ProcessData = FFDEC_ProcessData;	GF_REGISTER_MODULE_INTERFACE(ptr, GF_MEDIA_DECODER_INTERFACE, "FFMPEG decoder", "gpac distribution");	return (GF_BaseInterface *) ptr;}void FFDEC_Delete(void *ifce){	GF_BaseDecoder *dec = ifce;	FFDec *ffd = dec->privateStack;	if (ffd->ctx) avcodec_close(ffd->ctx);	free(ffd);	free(dec);}

⌨️ 快捷键说明

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