ffmpeg代码实现自定义decoder

来源:互联网 发布:商丘学院网络教学平台 编辑:程序博客网 时间:2024/04/30 10:30

1、概述

本文主要讲述如何用ffmpeg代码实现自己的decoder。

2、代码

/* *本程序主要实现一个自己的decoder并加入到decoder链中去,供api调用*作者:缪国凯(MK) *821486004@qq.com *2015-6-4 */ #include "stdafx.h"#ifdef __cplusplusextern "C"{#endif#include <libavformat/avformat.h>#include <libavcodec/avcodec.h>#include <libavutil/pixdesc.h>##ifdef __cplusplus};#endif#pragma comment(lib, "avcodec.lib")#pragma comment(lib, "avformat.lib")#pragma comment(lib, "avutil.lib")//#pragma comment(lib, "avdevice.lib")//#pragma comment(lib, "avfilter.lib")//#pragma comment(lib, "postproc.lib")//#pragma comment(lib, "swresample.lib")//#pragma comment(lib, "swscale.lib")static av_cold int mk_init_decoder(AVCodecContext *avctx){return 0;}static int mk_decode(AVCodecContext *avctx, void *data, int *got_frame,AVPacket *avpkt){AVFrame   *frame   = (AVFrame*)data;AVPicture *picture = (AVPicture*)data;const uint8_t *buf             = avpkt->data;int buf_size                   = avpkt->size;int size = avpicture_get_size(avctx->pix_fmt, avctx->width,avctx->height);frame->pict_type        = AV_PICTURE_TYPE_I;frame->key_frame        = 1;frame->buf[0] = av_buffer_alloc(size);memcpy(frame->buf[0]->data, buf, buf_size);int res = 0;if ((res = avpicture_fill(picture, frame->buf[0]->data, avctx->pix_fmt,avctx->width, avctx->height)) < 0) {av_buffer_unref(&frame->buf[0]);return res;}*got_frame = 1;return 0;}static av_cold int mk_close_decoder(AVCodecContext *avctx){return 0;}AVCodec ff_mkvideo_decoder = {/*.name           = */"mkvideo",/*.long_name      = */"mk video",/*.type           = */AVMEDIA_TYPE_VIDEO,/*.id             = */AV_CODEC_ID_MKVIDEO,/*.capabilities= */CODEC_CAP_PARAM_CHANGE,/*.supported_framerates = */NULL,/*.pix_fmts= */NULL,/*.supported_samplerates = */NULL,/*.sample_fmts= */NULL,/*.channel_layouts = */NULL,/*.max_lowres= */0,/*.priv_class= */NULL,/*.profiles= */NULL,/*.priv_data_size= */0,/*.next= */NULL,/*.init_thread_copy = */NULL,/*.update_thread_context = */NULL,/*.defaults= */NULL,/*.init_static_data = */NULL,/*.init           = */mk_init_decoder,/*.encode_sub= */NULL,/*.encode2        = */NULL,/*.decode= */mk_decode,/*.close          = */mk_close_decoder,};void help(){printf("**********************************************\n");printf("Usage:\n");printf("    MyMuxer [inputfile.mk] [outputfile] [size]\n");printf("\n");printf("Examples: \n");printf("    MyMuxer a.mk a.avi 1280x720\n");printf("**********************************************\n");  }int _tmain(int argc, _TCHAR* argv[]){if(argc < 4|| (!strcmp(argv[1],"--help"))){help();return 0;}av_register_all();avcodec_register(&ff_mkvideo_decoder);AVFormatContext *in_fxt = NULL, *out_fxt = NULL;AVStream *out_stream = NULL;int video_index = -1;AVDictionary *param = 0;av_dict_set(¶m, "video_size", argv[3], 0);if (avformat_open_input(&in_fxt, argv[1], NULL, ¶m) < 0){printf("can not open the input file context!\n");goto end;}if (avformat_find_stream_info(in_fxt, NULL) < 0){printf("can not find the stream info!\n");goto end;}if(avformat_alloc_output_context2(&out_fxt, NULL, NULL, argv[2]) < 0){printf("can not alloc output context!\n");goto end;}for (int i = 0; i < in_fxt->nb_streams; i++){if (in_fxt->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){//open decoderAVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_MKVIDEO);//由于ffmpeg源码里 还没把mk demuxer的codecid改过来,所以这里强制赋值,不然avcodec_open2打不开in_fxt->streams[i]->codec->codec_id = AV_CODEC_ID_MKVIDEO;if(0 > avcodec_open2(in_fxt->streams[i]->codec, codec, NULL)){printf("can not find or open decoder!\n");goto end;}video_index = i;//new streamout_stream = avformat_new_stream(out_fxt, NULL);if (!out_stream){printf("can not new stream for output!\n");goto end;}//set codec context paramout_stream->codec->codec = avcodec_find_encoder(out_fxt->oformat->video_codec);out_stream->codec->height = in_fxt->streams[i]->codec->height;out_stream->codec->width = in_fxt->streams[i]->codec->width;out_stream->codec->time_base = in_fxt->streams[i]->time_base;//out_stream->codec->time_base.den = 25;out_stream->codec->sample_aspect_ratio = in_fxt->streams[i]->codec->sample_aspect_ratio;out_stream->codec->pix_fmt = in_fxt->streams[i]->codec->pix_fmt;out_stream->avg_frame_rate.den = out_stream->codec->time_base.num;out_stream->avg_frame_rate.num = out_stream->codec->time_base.den;if (!out_stream->codec->codec){printf("can not find the encoder!\n");goto end;}if ((avcodec_open2(out_stream->codec, out_stream->codec->codec, NULL)) < 0){printf("can not open the encoder\n");goto end;}if (out_fxt->oformat->flags & AVFMT_GLOBALHEADER)out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;break;}}if (-1 == video_index){printf("found no video stream in input file!\n");goto end;}if (!(out_fxt->oformat->flags & AVFMT_NOFILE)){if(avio_open(&out_fxt->pb, argv[2], AVIO_FLAG_WRITE) < 0){printf("can not open output file handle!\n");goto end;}}if(avformat_write_header(out_fxt, NULL) < 0){printf("can not write the header of the output file!\n");goto end;}AVPacket pkt_in, pkt_out;av_init_packet(&pkt_in);av_init_packet(&pkt_out);int got_frame, got_picture;int i = 0, frame_index = 0;while(1){AVFrame *frame;frame = av_frame_alloc();got_frame = -1;got_picture = -1;if (av_read_frame(in_fxt, &pkt_in) < 0){break;}frame->buf;if (avcodec_decode_video2(in_fxt->streams[video_index]->codec, frame, &got_frame, &pkt_in) < 0){printf("can not decoder a frame");break;}av_free_packet(&pkt_in);if (got_frame){frame->pts = i++;pkt_out.data = NULL;//主要这里必须自己初始化,或者必须置为null,不然ff_alloc_packet2函数会报错pkt_out.size = 0;if (avcodec_encode_video2(out_stream->codec, &pkt_out, frame, &got_picture) < 0){printf("can not encode a frame!\n");break;}if (got_picture){printf("Succeed to encode frame: %5d\tsize:%5d\n",frame_index,pkt_out.size);pkt_out.stream_index = out_stream->index;frame_index++;av_write_frame(out_fxt, &pkt_out);av_free_packet(&pkt_out);}}av_frame_free(&frame);}av_write_trailer(out_fxt);//cleanavcodec_close(out_stream->codec);avcodec_close(out_fxt->streams[video_index]->codec);end:avformat_close_input(&in_fxt);if (out_fxt && !(out_fxt->oformat->flags & AVFMT_NOFILE)){avio_close(out_fxt->pb);}avformat_free_context(out_fxt);return 0;}

3、解释

原理和前面的自定义的muxer、demuxer、encoder一样,在这里就不多说了。
0 0
原创粉丝点击