解码本地视频流基本和解码音频流一致

视频解码过程

FFmpeg流程

关键函数啥的就不多说了 直接看我之前解码音频的文章 代码如下

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#include <libavutil/frame.h>
#include <libavutil/mem.h>#include <libavcodec/avcodec.h>#define VIDEO_INBUF_SIZE 20480
#define VIDEO_REFILL_THRESH 4096static char err_buf[128] = {0};
static char* av_get_err(int errnum)
{av_strerror(errnum, err_buf, 128);return err_buf;
}static void print_video_format(const AVFrame *frame)
{printf("width: %u\n", frame->width);printf("height: %u\n", frame->height);printf("format: %u\n", frame->format);// 格式需要注意
}static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame,FILE *outfile)
{int ret;/* send the packet with the compressed data to the decoder */ret = avcodec_send_packet(dec_ctx, pkt);if(ret == AVERROR(EAGAIN)){fprintf(stderr, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");}else if (ret < 0){fprintf(stderr, "Error submitting the packet to the decoder, err:%s, pkt_size:%d\n",av_get_err(ret), pkt->size);return;}/* read all the output frames (infile general there may be any number of them */while (ret >= 0){// 对于frame, avcodec_receive_frame内部每次都先调用ret = avcodec_receive_frame(dec_ctx, frame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)return;else if (ret < 0){fprintf(stderr, "Error during decoding\n");exit(1);}static int s_print_format = 0;if(s_print_format == 0){s_print_format = 1;print_video_format(frame);}// 一般H264默认为 AV_PIX_FMT_YUV420P, 具体怎么强制转为 AV_PIX_FMT_YUV420P 在音视频合成输出的时候讲解// frame->linesize[1]  对齐的问题// 正确写法  linesize[]代表每行的字节数量,所以每行的偏移是linesize[]for(int j=0; j<frame->height; j++)fwrite(frame->data[0] + j * frame->linesize[0], 1, frame->width, outfile);for(int j=0; j<frame->height/2; j++)fwrite(frame->data[1] + j * frame->linesize[1], 1, frame->width/2, outfile);for(int j=0; j<frame->height/2; j++)fwrite(frame->data[2] + j * frame->linesize[2], 1, frame->width/2, outfile);// 错误写法 用source.200kbps.766x322_10s.h264测试时可以看出该种方法是错误的//  写入y分量
//        fwrite(frame->data[0], 1, frame->width * frame->height,  outfile);//Y
//        // 写入u分量
//        fwrite(frame->data[1], 1, (frame->width) *(frame->height)/4,outfile);//U:宽高均是Y的一半
//        //  写入v分量
//        fwrite(frame->data[2], 1, (frame->width) *(frame->height)/4,outfile);//V:宽高均是Y的一半}
}
// 注册测试的时候不同分辨率的问题
// 提取H264: ffmpeg -i source.200kbps.768x320_10s.flv -vcodec libx264 -an -f h264 source.200kbps.768x320_10s.h264
// 提取MPEG2: ffmpeg -i source.200kbps.768x320_10s.flv -vcodec mpeg2video -an -f mpeg2video source.200kbps.768x320_10s.mpeg2
// 播放:ffplay -pixel_format yuv420p -video_size 768x320 -framerate 25  source.200kbps.768x320_10s.yuv
int main(int argc, char **argv)
{const char *outfilename;const char *filename;const AVCodec *codec;AVCodecContext *codec_ctx= NULL;AVCodecParserContext *parser = NULL;int len = 0;int ret = 0;FILE *infile = NULL;FILE *outfile = NULL;// AV_INPUT_BUFFER_PADDING_SIZE 在输入比特流结尾的要求附加分配字节的数量上进行解码uint8_t inbuf[VIDEO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];uint8_t *data = NULL;size_t   data_size = 0;AVPacket *pkt = NULL;AVFrame *decoded_frame = NULL;if (argc <= 2){fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]);exit(0);}filename    = argv[1];outfilename = argv[2];pkt = av_packet_alloc();enum AVCodecID video_codec_id = AV_CODEC_ID_H264;if(strstr(filename, "264") != NULL){video_codec_id = AV_CODEC_ID_H264;}else if(strstr(filename, "mpeg2") != NULL){video_codec_id = AV_CODEC_ID_MPEG2VIDEO;}else{printf("default codec id:%d\n", video_codec_id);}// 查找解码器codec = avcodec_find_decoder(video_codec_id);  // AV_CODEC_ID_H264if (!codec) {fprintf(stderr, "Codec not found\n");exit(1);}// 获取裸流的解析器 AVCodecParserContext(数据)  +  AVCodecParser(方法)parser = av_parser_init(codec->id);if (!parser) {fprintf(stderr, "Parser not found\n");exit(1);}// 分配codec上下文codec_ctx = avcodec_alloc_context3(codec);if (!codec_ctx) {fprintf(stderr, "Could not allocate audio codec context\n");exit(1);}// 将解码器和解码器上下文进行关联if (avcodec_open2(codec_ctx, codec, NULL) < 0) {fprintf(stderr, "Could not open codec\n");exit(1);}// 打开输入文件infile = fopen(filename, "rb");if (!infile) {fprintf(stderr, "Could not open %s\n", filename);exit(1);}// 打开输出文件outfile = fopen(outfilename, "wb");if (!outfile) {av_free(codec_ctx);exit(1);}// 读取文件进行解码data      = inbuf;data_size = fread(inbuf, 1, VIDEO_INBUF_SIZE, infile);while (data_size > 0){if (!decoded_frame){if (!(decoded_frame = av_frame_alloc())){fprintf(stderr, "Could not allocate audio frame\n");exit(1);}}ret = av_parser_parse2(parser, codec_ctx, &pkt->data, &pkt->size,data, data_size,AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);if (ret < 0){fprintf(stderr, "Error while parsing\n");exit(1);}data      += ret;   // 跳过已经解析的数据data_size -= ret;   // 对应的缓存大小也做相应减小if (pkt->size)decode(codec_ctx, pkt, decoded_frame, outfile);if (data_size < VIDEO_REFILL_THRESH)    // 如果数据少了则再次读取{memmove(inbuf, data, data_size);    // 把之前剩的数据拷贝到buffer的起始位置data = inbuf;// 读取数据 长度: VIDEO_INBUF_SIZE - data_sizelen = fread(data + data_size, 1, VIDEO_INBUF_SIZE - data_size, infile);if (len > 0)data_size += len;}}/* 冲刷解码器 */pkt->data = NULL;   // 让其进入drain modepkt->size = 0;decode(codec_ctx, pkt, decoded_frame, outfile);fclose(outfile);fclose(infile);avcodec_free_context(&codec_ctx);av_parser_close(parser);av_frame_free(&decoded_frame);av_packet_free(&pkt);printf("main finish, please enter Enter and exit\n");return 0;
}

ffmpeg 解码本地裸视频流相关推荐

  1. android全平台基于ffmpeg解码本地MP4视频推流到RTMP服务器

    音视频实践学习 android全平台编译ffmpeg以及x264与fdk-aac实践 ubuntu下使用nginx和nginx-rtmp-module配置直播推流服务器 android全平台编译ffm ...

  2. 【Qt+FFmpeg】FFmpeg解码本地视频流程

    目录 一.视频播放器的实现框架 1.解封装(Demuxing) 2.解码(Decode) 3.音视频同步 二.FFmpeg解码视频流程 1.FFmpeg解码视频流程图 2. 代码实现 一.视频播放器的 ...

  3. ffmpeg 解码本地无封装裸音频流 AAC MP3 复制代码就可以运行

    ⾳频解码过程 FFmpeg对应流程 关键函数说明: avcodec_find_decoder:根据指定的AVCodecID查找注册的解码器. av_parser_init:初始化AVCodecPars ...

  4. FFmpeg解码H264裸流并转换成opencv Mat

    感谢雷霄骅博士的在中文视频编解码的付出,http://blog.csdn.net/leixiaohua1020 最近要搞一些视频推流的事情,要解析H264裸流并且获取opencv格式的Mat数据给算法 ...

  5. android推流局域网,android全平台基于ffmpeg解码本地MP4视频推流到RTMP服务器

    音视频实践学习 本文目录 概述 还是先从最简单的搞起来,先从最基本的视频推流开始,要知道在电脑上使用ffmpeg完成推流,简直不要太简单,直接使用ffmpeg的推流命令即可,今天想在android平台 ...

  6. ffmpeg解码H264缺少帧的解决办法

    最近用ffmpeg解码H264裸码流文件,发现解码总是少几帧.上网查了些资料,解决了. 当使用avcodec_decode_video2时,如果第三个参数的值为1,则表示完成一帧的解码,如果为0,表示 ...

  7. ffmpeg 找不到bin_FFmpeg开发笔记(九):ffmpeg解码rtsp流并使用SDL同步播放

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109603499 各位读者,知识无穷而人力有穷 ...

  8. 用surfaceview播放FFmpeg解码视屏

    关于FFmpeg解码请看第一篇教程:FFmpeg解码 下载转码库libyuv 一般我们用surfaceview播放视频都是才用RGBA格式等播放的,但我们解码之后的视频可能是h.264等等 所以我们这 ...

  9. 使用ffmpeg解码音频sdl(push)播放

    自定义播放器系列 第一章 视频渲染 第二章 音频(push)播放(本章) 第三章 音频(pull)播放 第四章 实现时钟同步 第五章 实现通用时钟同步 第六章 实现播放器 文章目录 自定义播放器系列 ...

最新文章

  1. python爬虫抓取信息_python爬虫爬取网上药品信息并且存入数据库
  2. CUDA Samples: approximate prior vbox layer
  3. 一款 Java 开源的 Spring Boot 即时通讯 IM 聊天系统
  4. 【ARM】Tiny4412裸机编程之LED(一)
  5. 程序员面试金典 - 面试题 01.07. 旋转矩阵(一次遍历+位运算)
  6. uni-calendar更改打点颜色实现签到和缺勤不同打点颜色效果
  7. 服务器虚拟化十大因素
  8. C++ 类模板三(类模版中的static关键字)
  9. 和opengl的关系_从零开始的图形学学习(零):一切的开始 —— 自建OpenGL开发框架...
  10. android 自定义listview 多列,android listview的多列模版实例代码
  11. PHP往doc中插入图片
  12. 诺奖这么多,经济还崩溃了?
  13. 微pe添加网络组件_Nature子刊 | 微塑料影响微生物群落和氮循环
  14. ef联表查询速度_这个列式数据库牛!20亿行的查询,1s完成
  15. Adobe reader update 无法将数值disableexceptionchainvaliddation写入键/sofeware...请验证您对该有足够
  16. SDUT最短路径问题 1867————最短路
  17. STM32模拟USB多点触控屏
  18. 酷睿i5 12500H相当于什么水平 i512500H属于哪个档次
  19. 区别wchar_t,char,WCHAR
  20. Apache rewrite URL静态化配置与参数详解

热门文章

  1. Java实现2+22+222+2222+22222
  2. 无人机航测作业流程,你会几个?
  3. MyCat实现MySQL读写分离(双主双从多库)
  4. ajax请求无法下载文件
  5. Headless Services无头服务
  6. 用计算机求函数公式,计算机函数
  7. 30本,推荐一份互联网书单
  8. 怎样绕过计算机密码,如何利用U盘绕过电脑开机密码
  9. AC. Anu Has a Function
  10. 【雕刻机】高质量双面PCB板的全过程