ffmpeg 解码流程
来源:互联网 发布:典型网络暴力事件盘点 编辑:程序博客网 时间:2024/06/06 17:27
定义三个函数处理解码h264
1.编码前初始化,返回视频宽高
int* decode_init(char * in_filename){ avcodec_register_all(); av_register_all(); decode_frame = av_frame_alloc(); AVPacket pkt; //获取各种上下文 if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) { retu = -1; goto end; } if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) { retu = -2; goto end; } //例遍流,找到流所对应得下标 for (i = 0; i < ifmt_ctx->nb_streams; i++) { //Create output AVStream according to input AVStream AVFormatContext *ofmt_ctx; AVStream *in_stream = ifmt_ctx->streams[i]; AVStream *out_stream = NULL; if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoindex = i; } } //open decoder video_dec_ctx = ifmt_ctx->streams[videoindex]->codec; video_dec = avcodec_find_decoder(video_dec_ctx->codec_id); if(avcodec_open2(video_dec_ctx,video_dec,NULL)<0) { retu = -3; goto end; } double g_height = ifmt_ctx->streams[videoindex]->codec->height; double g_width = ifmt_ctx->streams[videoindex]->codec->width; int* wh = malloc(sizeof(int)*2); wh[0] = g_width; wh[1] = g_height;end: if(retu != 0) return NULL; else return wh;}
2.解码一帧,返回该帧不用释放,该变量作用域是文件,所以想要支持多线程并发解码,需要将其所用参数封装为结构体存储。
AVFrame* decode_next(){ if(decode_frame!=NULL) av_frame_unref(decode_frame); int ret = 0; int got_frame = 0; int error_time = 0; while(1) { //Get an AVPacket if (av_read_frame(ifmt_ctx, &pkt) < 0) { av_free_packet(&pkt); goto decode_free; } if (pkt.stream_index == videoindex) { ret = avcodec_decode_video2(video_dec_ctx,decode_frame, &got_frame, &pkt); if(got_frame) goto decode_success; else { if(failed_times ++<30) continue; else goto decode_free; } } av_free_packet(&pkt); }decode_free: av_free_packet(&pkt); return NULL;decode_success: return decode_frame;}
如果是某些特殊编码(比如h264、h265),在读取packet失败之后就停止解码会丢掉末尾的帧。具体原因分析点击这里。
所以要在读取packet失败之后接着调用解码,获取剩余的帧。使用一个变量failed_times 记录编码器中存在的帧数。在读取结束之后接着调用failed_times 次avcodec_decode_video2
修改如下:
int failed_times = 0;int read_packet_failed = 0;AVFrame* decode_next(){ if(decode_frame!=NULL) av_frame_unref(decode_frame); int ret = 0; int got_frame = 0; int error_time = 0; while(1) { //Get an AVPacket if (av_read_frame(ifmt_ctx, &pkt) < 0) { read_packet_failed = 1; av_free_packet(&pkt); if(failed_times > 0) { failed_times--; goto decode; } else goto decode_free; } if (pkt.stream_index == videoindex) { decode: ret = avcodec_decode_video2(video_dec_ctx,decode_frame, &got_frame, &pkt); if(got_frame) goto decode_success; else { if(read_packet_failed) goto decode_free; else { failed_times ++; continue; } else goto decode_free; } } av_free_packet(&pkt); }decode_free: av_free_packet(&pkt); return NULL;decode_success: return decode_frame;}
3.解码完成之后释放。
int decode_release(){ avcodec_close(video_dec_ctx); // av_free(video_dec_ctx); avformat_close_input(&ifmt_ctx); if(decode_frame!=NULL) { av_frame_free(&decode_frame); decode_frame = NULL; }}
0 0
- FFMpeg的解码流程
- FFMpeg的解码流程
- FFMPEG解码流程
- ffmpeg解码流程
- ffmpeg解码流程
- FFMpeg的解码流程
- ffmpeg解码流程
- FFMPEG解码流程
- FFMpeg的解码流程
- FFMPEG解码流程
- ffmpeg解码流程 .
- ffmpeg解码流程
- ffmpeg解码流程
- FFMpeg的解码流程
- ffmpeg解码流程
- FFMPEG解码流程
- FFMPEG解码流程
- FFMpeg的解码流程
- 基于SpringBoot的通用设备操作接口服务
- iOS缓存清理
- lua eval
- CALayer使用(1)
- Spring Batch 之 Spring Batch 简介(一)
- ffmpeg 解码流程
- 安卓开发中@SuppressLint( NewApi )问题的解决方法
- linux下的open函数中的mode问题
- JS使用document.write输出时换行符的使用
- 实验二:网络测试命令和工具的使用
- 2637: 编程题:类---矩形类
- Spring Batch 之 Sample(Hello World)(三)
- HDU 5122 水题
- 关于CSS中的float和position (父容器div内的子元素div为float时,父元素无法撑开(或高度自适应)的解决方式)