ffmpeg 编码 png apng图片

来源:互联网 发布:vivo一键锁屏软件 编辑:程序博客网 时间:2024/05/21 22:22

ffmpeg 编码 png apng图片

1. 搭建环境
首先需要搭建ubuntu下,ffmpeg开发环境,这个网上有很多在这里就不多叙述了


2.  定义编码器相关的结构体
typedef struct Encode_PNG_Key{AVFormatContext* pFormatCtx;  AVOutputFormat* fmt;  AVStream* video_st; AVCodecContext* pCodecCtx;AVCodec* pCodec;  } Encode_Png_key;

3. 初始化编码器

这个需要你特别注意,再找编码器格式的千万不要av_guess_format(NULL,  "out.png", NULL);
中间的png找到的是JPEG的编码器,通过阅读源码很容易发现,所以如果你确定是编码png,切记要下边方式找到输出的编码器
int encode_png_init(Encode_Png_key *args, char *filename, int width, int height, const enum AVPixelFormat pix_fmt){int ret = 0;if (args == NULL || filename == NULL )return -1;args->pFormatCtx = avformat_alloc_context();//Guess formatargs->fmt = av_guess_format(NULL, NULL, "image/png");if (args->fmt == NULL){ret = -1;dm_printf("av_guess_format fail.");goto end;}args->pFormatCtx->oformat = args->fmt;//Output URLif (avio_open(&args->pFormatCtx->pb, filename, AVIO_FLAG_READ_WRITE) < 0){dm_printf("Couldn't open output file.");ret = -1;goto end;}//Method 2. More simple//avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file);//fmt = pFormatCtx->oformat;args->video_st = avformat_new_stream(args->pFormatCtx, 0);if (args->video_st == NULL){ret = -1;goto end;}args->pCodecCtx = args->video_st->codec;args->pCodecCtx->codec_id = args->fmt->video_codec;args->pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;args->pCodecCtx->pix_fmt = pix_fmt;args->pCodecCtx->width = width;args->pCodecCtx->height = height;args->pCodecCtx->time_base.num = 1;args->pCodecCtx->time_base.den = 25;//Output some informationav_dump_format(args->pFormatCtx, 0, filename, 1);args->pCodec = avcodec_find_encoder(args->pCodecCtx->codec_id);if (!args->pCodec){dm_printf("Codec not found.");ret = -1;goto end;}if (avcodec_open2(args->pCodecCtx, args->pCodec, NULL) < 0){dm_printf("Could not open codec.");ret = -1;goto end;}//Write Headeravformat_write_header(args->pFormatCtx, NULL);end:if (ret < 0){if (args->video_st){avcodec_close(args->video_st->codec);}if (args->pFormatCtx != NULL && args->pFormatCtx->pb != NULL){avio_close(args->pFormatCtx->pb);}if (args->pFormatCtx != NULL)avformat_free_context(args->pFormatCtx);memset(args, 0, sizeof(Encode_Png_key));}return ret;}

4,编码一桢图片

int encode_png(Encode_Png_key *args, AVFrame *frame){int ret = -1;int got_frame = 0;AVPacket  packet;memset(&packet, 0, sizeof(packet));if (args == NULL  || args->pCodecCtx == NULL){dm_printf("args == NULL || filt_frame== NULL || args->pCodecCtx == NULL");return -1;}av_init_packet(&packet);packet.data = NULL;//Encoderet = avcodec_encode_video2( args->pCodecCtx, &packet, frame, &got_frame);if(ret < 0){dm_printf("Encode Error.\n");return -1;}if (got_frame == 1){packet.stream_index =  args->video_st->index;ret = av_write_frame( args->pFormatCtx, &packet);}elsevflush_encoder(args->pFormatCtx, 0);av_free_packet(&packet);args->pCodecCtx->frame_number = 0;return ret;}


5, 释放资源

int encode_png_release(Encode_Png_key *args){if (args != NULL){if (args->pFormatCtx != NULL){//Write Trailerav_write_trailer(args->pFormatCtx);}if (args->video_st){avcodec_close(args->video_st->codec);}if (args->pFormatCtx != NULL && args->pFormatCtx->pb != NULL){avio_close(args->pFormatCtx->pb);}if (args->pFormatCtx != NULL)avformat_free_context(args->pFormatCtx);memset(args, 0, sizeof(Encode_Png_key));}return 0;}

另外apng是无损压缩的png动图,这个比gif动态效果好,非常适合手机端动图开发


原创粉丝点击