FFMPEG 视频图像解封装解码

FFMPEG4.0 音频解码解封装
FFMPEG 音频封装编码

下面的函数方法基于最新的FFMPEG 4.0(4.X):
本文讲是如何从一个视频文件中提取出其中的图像数据,并将图像数据保存到文件中。

解码解封装的过程与音频差不多,具体如下:
1.读取视频文件的格式信息

    fmt_ctx = avformat_alloc_context();
    avformat_open_input(&fmt_ctx,input,NULL,NULL);
    avformat_find_stream_info(fmt_ctx,NULL);

2.获取视频流

    int st_index = av_find_best_stream(fmt_ctx,AVMEDIA_TYPE_VIDEO,-1,-1,NULL,0);
    LOGV("st_index = %d\n",st_index);
    AVStream *st = fmt_ctx->streams[st_index];

3.准备×××与解码context

    AVCodec *codec = avcodec_find_decoder(st->codecpar->codec_id);
    AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);

4.拷贝视频流中的参数到×××context中并打开×××

    avcodec_parameters_to_context(codec_ctx,st->codecpar);
    avcodec_open2(codec_ctx,codec,NULL);

5.读取视频的格式、宽高信息

    int width = codec_ctx->width;
    int height = codec_ctx->height;
    enum AVPixelFormat pixel_fmt = codec_ctx->pix_fmt;

6.申请图像存储空间

    uint8_t *dst_buf[4] = {0};
    int      dst_linesize[4];
    int size = av_image_alloc(dst_buf,dst_linesize,width,height,pixel_fmt,1);

7.申明存储原始数据与解码后数据的packet与frame

    AVFrame *frame = av_frame_alloc();
    AVPacket *packet = av_packet_alloc();

8.读取数据,只取用视频数据

int ret = av_read_frame(fmt_ctx,packet);
//读取到的packet不仅仅是图像数据,还有音频、字幕等数据。
if(packet->stream_index != st_index)
{
    continue;
}

9.发送数据进行解码
ret = avcodec_send_packet(codec_ctx,packet);
10.接收解码后的原始数据,这是个反复的过程,一个packet可能解码出好几个frame

        ret = avcodec_receive_frame(codec_ctx,frame);
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) //packet解码完了,需要sent
                break;
            if(ret < 0) {
                return 1;
            }

注意:收到的frame可能存在宽高或者fmt格式变化这种情况,后面的流程代码没有考虑这种情况(这种奇葩视频应该不会遇到)

            if(frame->width != width || frame->height != height || frame->format != pixel_fmt)
            {
                LOGV("eeeeeeeeeeeee");
            }

11.把frame中的数据拷贝到事先准备的dst_buf中。二维指针数组看作一位数组。
av_image_copy(dst_buf,dst_linesize,frame-&gt;data,frame-&gt;linesize,pixel_fmt,width,height);
12.把数据写入文件。
fwrite(dst_buf[0],1,size,out_file);

下面贴一段完整的示例代码,代码没有考虑失败的情况,结尾没有搞释放,也没有flush×××,示例只是为了掌握整个核心解码流程。

/*
 * demuxing_decode_video.c
 *
 *  Created on: 2019年1月8日
 *      Author: deanliu
 */

#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>

static char log_buf[1024*8];
#define LOGV(...) av_log(NULL,AV_LOG_VERBOSE,__VA_ARGS__)

void ffmpeg_log_callback(void* ptr, int level, const char* fmt, va_list vl)
{
    static int print_prefix = 1;
    av_log_format_line(ptr,level,fmt,vl,log_buf,sizeof(log_buf),&print_prefix);
    fprintf(stderr,"%s",log_buf);
}

int main()
{
    av_log_set_callback(ffmpeg_log_callback);

    char *input = "E:/测试音视频/12种格式视频/test.avi";
    char *output = "d:/video.v";

    FILE *out_file = fopen(output,"wb");

    AVFormatContext *fmt_ctx;

    fmt_ctx = avformat_alloc_context();
    avformat_open_input(&fmt_ctx,input,NULL,NULL);
    avformat_find_stream_info(fmt_ctx,NULL);

    int st_index = av_find_best_stream(fmt_ctx,AVMEDIA_TYPE_VIDEO,-1,-1,NULL,0);
    LOGV("st_index = %d\n",st_index);
    AVStream *st = fmt_ctx->streams[st_index];

    AVCodec *codec = avcodec_find_decoder(st->codecpar->codec_id);
    AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);

    avcodec_parameters_to_context(codec_ctx,st->codecpar);
    avcodec_open2(codec_ctx,codec,NULL);

    int width = codec_ctx->width;
    int height = codec_ctx->height;
    enum AVPixelFormat pixel_fmt = codec_ctx->pix_fmt;

    uint8_t *dst_buf[4] = {0};
    int      dst_linesize[4];
    int size = av_image_alloc(dst_buf,dst_linesize,width,height,pixel_fmt,1);

    AVFrame *frame = av_frame_alloc();
    AVPacket *packet = av_packet_alloc();

    while(1)
    {
        LOGV("READ\n");
        int ret = av_read_frame(fmt_ctx,packet);
        if(ret < 0){
            LOGV("ret = %d\n",ret);
            break;
        }
        if(packet->stream_index != st_index)
        {
            continue;
        }
        LOGV("SENT\n");
        ret = avcodec_send_packet(codec_ctx,packet);
        if(ret < 0){
            return 1;
        }

        while(ret >= 0)
        {
            LOGV("receiver\n");
            ret = avcodec_receive_frame(codec_ctx,frame);
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
                break;
            if(ret < 0) {
                return 1;
            }
            if(frame->width != width || frame->height != height || frame->format != pixel_fmt)
            {
                LOGV("eeeeeeeeeeeee");
            }
            av_image_copy(dst_buf,dst_linesize,frame->data,frame->linesize,pixel_fmt,width,height);
            LOGV("dst_buf = %d,%d,%d,%d\n",dst_buf[2][0],dst_buf[1][1],dst_buf[0][2],dst_buf[0][3]);
            fwrite(dst_buf[0],1,size,out_file);

        }
    }

    LOGV("dst_linesize = %d,%d,%d,%d\n",dst_linesize[0],dst_linesize[1],dst_linesize[2],size);
    printf("Play the output video file with the command:\n"
           "ffplay -f rawvideo -pix_fmt %s -video_size %dx%d %s\n",
           av_get_pix_fmt_name(pixel_fmt), width, height,
           output);

    LOGV("END!!");

    fclose(out_file);

    return 0;
}

原文地址:https://blog.51cto.com/4095821/2402711

时间: 2024-10-03 13:40:52

FFMPEG 视频图像解封装解码的相关文章

【FFMpeg视频开发与应用基础】四、调用FFmpeg SDK解析封装格式的视频为音频流和视频流

<FFMpeg视频开发与应用基础--使用FFMpeg工具与SDK>视频教程已经在"CSDN学院"上线,视频中包含了从0开始逐行代码实现FFMpeg视频开发的过程,欢迎观看!链接地址:FFMpeg视频开发与应用基础--使用FFMpeg工具与SDK 工程代码地址:FFmpeg_Tutorial 我们平常最常用的音视频文件通常不是单独的音频信号和视频信号,而是一个整体的文件.这个文件会在其中包含音频流和视频流,并通过某种方式进行同步播放.通常,文件的音频和视频通过某种标准格式进行

视频编码与封装方式详解

http://blog.csdn.net/attilax/article/details/5807047 1.    编码方式和封装格式    1 2.    视频编码标准两大系统    2 MPEG-1. 2 MPEG-2. 3 MPEG-3. 3 MPEG-4. 3 ITU-T. 4 WMV.. 4 3.    常用视频编码方式有Xvid( 4 4.    常见存储封装格式    6 5.    几种常见的转换格式设置    7 6.    无损视频编码    9 1.   编码方式和封装格

视频编解码的理论和实践2:Ffmpeg视频编解码

近几年,视频编解码技术在理论及应用方面都取得了重大的进展,越来越多的人想要了解编解码技术.因此,网易云信研发工程师为大家进行了归纳梳理,从理论及实践两个方面简单介绍视频编解码技术. 相关阅读推荐 <视频直播关键技术:流畅.拥塞和延时追赶> <视频直播技术详解:直播的推流调度> <音视频通话:小议音频处理与压缩技术> <视频编解码的理论和实践1:基础知识介绍>   1.Ffmpeg介绍 <视频编解码的理论和实践1:基础知识介绍>介绍了视频编码的基础

【FFMpeg视频开发与应用基础】五、调用FFMpeg SDK封装音频和视频为视频文件

<FFMpeg视频开发与应用基础--使用FFMpeg工具与SDK>视频教程已经在"CSDN学院"上线,视频中包含了从0开始逐行代码实现FFMpeg视频开发的过程,欢迎观看!链接地址:FFMpeg视频开发与应用基础--使用FFMpeg工具与SDK 工程代码地址:FFmpeg_Tutorial 音频和视频的封装过程为解封装的逆过程,即将独立的音频数据和视频数据按照容器文件所规定的格式封装为一个完整的视频文件的过程.对于大多数消费者来说,视频封装的容器是大家最为熟悉的,因为它直接

转:FFmpeg的远程视频监控系统编解码

0 引言 随着视频编解码技术.计算机网络技术.数字信号处理技术和嵌入式系统的发展,以嵌入式网络视频服务器为核心的远程视频监控系统开始在市场上崭露头角.该系统把摄像机输出的模拟视频信号通过内置的嵌入式视频编码器直接转换成视频流,通过计算机网络传输出去.嵌入式网络视频服务器具备视频编码处理.网络通信.系统控制等强大功能,直接支持网络视频传输和网络管理,使得监控范围达到前所未有的广度.在远程视频监控系统中,摄像头获取的原始视频流在传输之前需要压缩,而FFmpeg可以将原始视频压缩为H264格式视频流,

解密多媒体封装解封装框架

上一篇文章我们搭好了环境并编译出所需的ffmpeg库,本篇我们讨论如何利用ffmpeg提供的API函数进行多媒体文件的解封装(demux)过程.在讲解之前,我们需要了解一些基本的多媒体文件知识,大虾请飘过. 容器格式:不管是音频文件还是视频格式的文件,都是一个多媒体的容器,即container,比如常见的视频容器格式有avi.mp4.mkv.flv.rm/rmvb.mov.ts.vob.dat,音频容器格式有MP3.WAV.AAC.APE,FLAC等等,它容纳了视频.音频.字幕(subtitle

ffmpeg参数详解

a) 通用选项 -L license -h 帮助 -fromats 显示可用的格式,编解码的,协议的... -f fmt 强迫采用格式fmt,如image2.gif -i filename 输入文件 -y 覆盖输出文件 -t duration 设置纪录时间 hh:mm:ss[.xxx]格式的记录时间也支持 -ss position 搜索到指定的时间 [-]hh:mm:ss[.xxx]的格式也支持 -title string 设置标题 -author string 设置作者 -copyright

最简单的基于FFMPEG的图像编码器(YUV编码为JPEG)

伴随着毕业论文的完毕,这两天最终腾出了空暇,又有时间搞搞FFMPEG的研究了.想着之前一直搞的都是FFMPEG解码方面的工作,非常少涉及到FFMPEG编码方面的东西,于是打算研究一下FFMPEG的编码.在网上看了一些样例,发现要不然是难度稍微有些大,要不然就是类库比較陈旧,于是就决定自己做一个编码方面的样例,方便以后学习. 本文的编码器实现了YUV420P的数据编码为JPEG图片.本着简单的原则,代码基本上精简到了极限.使用了2014年5月6号编译的最新的FFMPEG类库. 程序非常easy,打

直播技术总结(四)音视频数据压缩及编解码基础

转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/60480109 音视频压缩技术是编解码中难点,常常会涉及很多算法处理问题.数据封装,转封装等,看下Agenda: 音视频为何需要压缩? 压缩编码的分类 常用压缩编码的方法 编码器中的关键技术 预测 量化 变换 熵编码 编解码中的情况 音视频为何需要压缩? 未经压缩的数字视频的数据量巨大 存储困难:一张DVD只能存储几秒钟的未压缩数字