使用libavcodec解码H264视频,C

2024-01-11

我正在尝试使用 ffmpeg/libavcodec 解码原始 h264 文件,但无法使其正常工作。目前输出应该是原始 YUV 文件。可以用GCC编译代码

gcc -o decoder decoder.c -L./lib/ -llibavcodec -llibavutil

avcodec.dll、avutil.dll 和 swresample.dll 必须放置在 .exe 启动的目录中。 CMD 中的输出看起来像这样(只是其中的一部分,但它总是这样):

[h264 @ 00a80f20] reference picture missing during reorder
[h264 @ 00a80f20] Missing reference picture, default is 65562
[h264 @ 00a80f20] error while decoding MB 80 54, bytestream -10
[h264 @ 00a80f20] concealing 1649 DC, 1649 AC, 1649 MV errors in B frame
[h264 @ 00a80f20] reference picture missing during reorder
[h264 @ 00a80f20] reference picture missing during reorder
[h264 @ 00a80f20] reference picture missing during reorder
[h264 @ 00a80f20] Missing reference picture, default is 65566
[h264 @ 00a80f20] Missing reference picture, default is 65566
[h264 @ 00a80f20] Missing reference picture, default is 65566
[h264 @ 00a80f20] reference picture missing during reorder
[h264 @ 00a80f20] Missing reference picture, default is 65568
[h264 @ 00a80f20] reference picture missing during reorder
[h264 @ 00a80f20] Missing reference picture, default is 65570
[h264 @ 00a80f20] reference picture missing during reorder

这是我的代码

#include <stdlib.h>
#include <stdio.h>

#ifdef HAVE_AV_CONFIG_H
#undef HAVE_AV_CONFIG_H
#endif

#include "libavcodec/avcodec.h"
//#include "libavcodec/libavutil/mathematics.h"

#define INBUF_SIZE 4096

void video_decode(char *outfilename, char *filename)
{
    AVCodec *codec;
    AVCodecContext *c= NULL;
    int frame, got_picture, len;
    FILE *f, *outf;
    AVFrame *picture;
    uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
    AVPacket avpkt;
    int i;

    av_init_packet(&avpkt);

    memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);

    codec = avcodec_find_decoder(AV_CODEC_ID_H264);
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

    c = avcodec_alloc_context3(codec);
    picture = av_frame_alloc();

    if((codec->capabilities)&CODEC_CAP_TRUNCATED)
        (c->flags) |= CODEC_FLAG_TRUNCATED;

    c->height = 1080;
    c->width = 1920;

    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }

    f = fopen(filename, "rb");
    if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }

    outf = fopen(outfilename,"w");
    if(!outf){
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }
    frame = 0;
    for(;;) {
        avpkt.size = fread(inbuf, 1, INBUF_SIZE, f);
        if (avpkt.size == 0)
            break;

        avpkt.data = inbuf;
        while (avpkt.size > 0) {

            len = avcodec_decode_video2(c, picture, &got_picture, &avpkt);

            if (len < 0) {
                fprintf(stderr, "Error while decoding frame %d\n", frame);
                exit(1);
            }
            if (got_picture) {
                printf("saving frame %3d\n", frame);
                fflush(stdout);
                for(i=0; i<c->height; i++)
                    fwrite(picture->data[0] + i * picture->linesize[0], 1, c->width, outf  );
                for(i=0; i<c->height/2; i++)
                    fwrite(picture->data[1] + i * picture->linesize[1], 1, c->width/2, outf );
                for(i=0; i<c->height/2; i++)
                    fwrite(picture->data[2] + i * picture->linesize[2], 1, c->width/2, outf );
                frame++;
            }
            avpkt.size -= len;
            avpkt.data += len;
        }
    }

    avpkt.data = NULL;
    avpkt.size = 0;
    len = avcodec_decode_video2(c,picture, &got_picture, &avpkt);
    if(got_picture) {
        printf("saving last frame %d\n",frame);
        fflush(stdout);
        for(i=0; i<c->height; i++)
            fwrite(picture->data[0] + i * picture->linesize[0], 1, c->width, outf );
        for(i=0; i<c->height/2; i++)
            fwrite(picture->data[1] + i * picture->linesize[1], 1, c->width/2, outf );
        for(i=0; i<c->height/2; i++)
            fwrite(picture->data[2] + i * picture->linesize[2], 1, c->width/2, outf );
        frame++;
    }

    fclose(f);
    fclose(outf);

    avcodec_close(c);
    av_free(c);
    av_frame_free(&picture);
    printf("\n");
}

int main(int argc, char **argv){
    avcodec_register_all();
    video_decode("test", "trailer.264");

    return 0;
}

我还尝试了不同格式的不同视频(当然,在本例中我更改了代码中的编解码器),例如 MPEG1、H263、H265,但这些都无法正常工作。 我希望有人可以帮助我并告诉我我在这里做错了什么。谢谢


avcodec_decode_video2 的每个输入数据包 (avpkt) 应包含一帧的完整(且仅)数据,即它不应在帧 NAL 的中间被截断。因此,以 4096 字节块读取和发送数据的代码将无法工作。您需要通过解析附件 B 数据并查找起始代码并分析 NAL 类型(在帧超过 1 个切片的情况下更是如此)来自行打包,或者使用 H.264 的 libavformat 解析器。作为 H.264 的解决方法,您可以尝试使用 CODEC_FLAG2_CHUNKS 标志,但我不确定它的可靠性如何,并且仍然认为 4096 字节块太小。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用libavcodec解码H264视频,C 的相关文章

  • Accept() 是线程安全的吗?

    我目前正在用 C 语言为我正在做的课程编写一个简单的网络服务器 我们的一项要求是实现一个线程池来使用 pthread 处理连接 我知道我将如何粗略地执行此操作 在主线程中调用accept并将文件描述符传递给freee线程 但是我的朋友建议了
  • 如何将十六进制字符串转换为十六进制数字[重复]

    这个问题在这里已经有答案了 可能的重复 如何将十六进制字符串转换为有符号整数 https stackoverflow com questions 3705429 how do i convert hex string into signed
  • 从 future 中检索值时的 SIGABRT

    我在使用 C 11 future 时遇到问题 当我打电话时wait or get 关于返回的未来std async 程序接收从mutex标头 可能是什么问题呢 如何修复它 我在 Linux 上使用 g 4 6 将以下代码粘贴到 ideone
  • Qt 计算和比较密码哈希

    目前正在 Qt 中为测验程序构建面向 Web 的身份验证服务 据我了解 在数据库中存储用户密码时 必须对其进行隐藏 以防落入坏人之手 流行的方法似乎是添加的过程Salt https en wikipedia org wiki Salt cr
  • 如何在 Asp.net Gridview 列中添加复选框单击事件

    我在 asp 中有一个 gridview 其中我添加了第一列作为复选框列 现在我想选择此列并获取该行的 id 值 但我不知道该怎么做 这是我的 Aspx 代码
  • 矩阵向量变换

    我正在编写一个代码来制作软件蒙皮器 骨骼 皮肤动画 并且我正处于 优化 阶段 蒙皮器工作得很好 并且在 Core 上 1 09 毫秒内对 4900 个三角形网格与 22 个骨骼进行蒙皮Duo 2 Ghz 笔记本 我需要知道的是 1 有人可以
  • 有没有办法使用 i387 fsqrt 指令获得正确的舍入?

    有没有办法使用 i387 fsqrt 指令获得正确的舍入 除了改变精确模式在 x87 控制字中 我知道这是可能的 但这不是一个合理的解决方案 因为它存在令人讨厌的重入型问题 如果 sqrt 操作中断 精度模式将出错 我正在处理的问题如下 x
  • 序列化和反序列化 Visual Studio 解决方案文件 - 或以编程方式编辑?

    我想以编程方式添加和删除项目 解决方案文件夹和其他项目 例如解决方案的资源文件 但我不确定最好的方法是什么 对于那些不知道的人 高度简化 解决方案文件 sln 通常如下所示 Microsoft Visual Studio Solution
  • 指向字节数组的指针

    由于 Misra C 的要求 我的一位同事想要使用指针声明 但我遇到了一些问题 Misra 安全关键指南 不会让我们纯粹的程序员使用指针 但会让我们对数组字节进行操作 他打算获取一个指向字节数组的指针 因此我们不会在堆栈上传递实际的数组 T
  • 格式化货币

    在下面的示例中 逗号是小数点分隔符 我有这个 125456 89 我想要这个 125 456 89 其他示例 23456789 89 gt 23 456 789 89 Thanks 看看这个例子 double value 12345 678
  • 在简单注入器中注册具有多个构造函数和字符串依赖项的类型

    我正在尝试弄清楚如何使用 Simple Injector 我在项目中使用了它 注册简单服务及其组件没有任何问题 但是 当组件具有两个以上实现接口的构造函数时 我想使用依赖注入器 public DAL IDAL private Logger
  • 将非算术类型作为参数传递给 cmath 函数是否有效?

    给定以下用户定义类型S具有转换功能double struct S operator double return 1 0 以及以下调用cmath http en cppreference com w cpp header cmath使用类型的
  • .NET JIT 编译的代码缓存在哪里?

    NET 程序首先被编译为 MSIL 代码 当它被执行时 JIT编译器会将其编译为本机机器代码 我想知道 这些JIT编译的机器代码存储在哪里 它只存储在进程的地址空间中吗 但由于程序的第二次启动比第一次快得多 我认为即使在执行完成后 该本机代
  • 使用(linq to sql)更新错误

    我有两个表 通过外键 CarrierID 绑定 Carrier CarrierID CarrierName CarrierID 1 CarrierName DHL CarrierID 2 CarrierName Fedex Vendor V
  • 如何访问窗口?

    我正在尝试使用其句柄访问特定窗口 即System IntPtr value Getting the process of Visual Studio program var process Process GetProcessesByNam
  • ASP.NET Core Razor Page 多路径路由

    我正在使用 ASP NET Core 2 0 Razor Pages 不是 MVC 构建系统 但在为页面添加多个路由时遇到问题 例如 所有页面都应该能够通过 abc com language 访问segment shop mypage 或
  • 如何将对象转换为传递给函数的类型?

    这不会编译 但我想做的只是将对象转换为传递给函数的 t public void My Func Object input Type t t object ab TypeDescriptor GetConverter t ConvertFro
  • 如何设置 CMake 与 clang 交叉编译 Windows 上的 ARM 嵌入式系统?

    我正在尝试生成 Ninja makefile 以使用 Clang 为 ARM Cortex A5 CPU 交叉编译 C 项目 我为 CMake 创建了一个工具链文件 但似乎存在错误或缺少一些我无法找到的东西 当使用下面的工具链文件调用 CM
  • g++ C++0x 枚举类编译器警告

    我一直在将可怕的 C 类型安全伪枚举重构为新的 C 0x 类型安全枚举 因为它们是way更具可读性 不管怎样 我在导出的类中使用它们 所以我明确地将它们标记为导出 enum class attribute visibility defaul
  • FindAsync 很慢,但是延迟加载很快

    在我的代码中 我曾经使用加载相关实体await FindAsync 希望我能更好地遵守 C 异步指南 var activeTemplate await exec DbContext FormTemplates FindAsync exec

随机推荐

  • 动态变量 Jekyll Liquid

    我想在 jekyll Liquid 安装中使用动态变量 我想使用动态变量动态访问 config yml 文件 名称 最好用一个例子来解释 Page layout default title title homepage 默认布局 site
  • 如何用Java更新MongoDb数据库?

    我是 MongoDb 的新手 有很多关于在 2 x 版本中更新集合的示例 但我找不到任何关于 3 x 版本的来源 Java代码 MongoClient mongoClient new MongoClient localhost 27017
  • 调整大小时避免在两个单词之间断行[重复]

    这个问题在这里已经有答案了 我有一个字符串 我需要它不要破坏不同行中的两个特定单词 例子 Ask for it it when contracting until 2016 09 30 with T 2 Rate 当我调整窗口大小并使其变小
  • Firebase 身份验证在应用删除后仍然存在? [复制]

    这个问题在这里已经有答案了 我刚刚发布了一个应用程序 它使用 Firebase 身份验证和 Gmail 来对用户进行身份验证 我注意到 如果有人登录然后删除该应用程序 如果他们重新下载该应用程序 他们仍然会使用 Firebase 登录 在我
  • 以编程方式重新启动 React Native 应用程序

    是否可以在不编写任何本机代码的情况下以编程方式重新启动 React Native 应用程序 例如 我从答案中知道这个问题 https stackoverflow com questions 15564614 how to restart a
  • 组织捕获和计时行为不当

    我相信你们中的一些人可能已经 从我最近提出的一系列问题中 了解到我正在 emacs 上设置组织模式并浏览 Brent Hansen 令人印象深刻的组织set up http doc norang ca org mode html 他是一个计
  • 在 for 循环中使用 ggplot2 绘制多个图

    我看了这些问题 1 https stackoverflow com questions 3824412 ggplot2 use options for multiple plots and 2 https stackoverflow com
  • UITableView 部分边框

    有没有办法在 UITableView 部分 组样式 上设置边框 我的意思并不是要更改该部分中单元格的边框 我想要整个部分周围有一个边框 像这样 Note 虽然上图仅显示了单个部分的一部分 但所讨论的表实际上有多个部分 每个部分的长度都是可变
  • 使用 google-api-php-client 下载文件

    我在尝试使用位于以下位置的 php 客户端从 Google Cloud Storage 下载文件时遇到问题https code google com p google api php client https code google com
  • Active Admin 中的自定义表单

    我正在 Active Admin 0 5 中创建自定义表单 我已经注册了一个页面并通过 DSL 创建了一个表单 ActiveAdmin register page Planning namespace gt pos admin do con
  • 如何使用html和css绘制虚线

    如何使用 html 和 css 绘制虚线 如下所示 不是虚线 可以使用这个边框 1px虚线 但需要增加破折号的长度尺寸 而不是宽度 Use repeating linear gradient https developer mozilla
  • 电话软件开发语言

    是否存在通用的手机开发语言 我的意思是 例如 php 或 java 或其他 编辑 我们必须开发一些电话应用程序 并且我们正在寻找不同设备 黑莓 iPhone 摩托罗拉等 中最好的可重用语言 Java 已经非常接近了 但它还远未达到通用性 i
  • 我可以在 Visual Basic 中使用 C++ 函数吗?

    我对编程有点陌生 但我已经制作了一个非常好的库来计算数学问题 例如二次方程和许多其他问题 现在我遇到了一个朋友 他正在用 VB 进行一些编程 我们在想是否可以将我的函数从 C 导入到他的代码中 以便他可以在需要时调用它们 这样我们就可以制作
  • 有没有办法删除逻辑应用运行历史记录/日志?

    有没有办法从逻辑应用中删除所有运行历史记录日志 我知道现在正在测试 日志保留时间 的预览 但删除所有日志的最频繁时间是每周一次 我需要能够更频繁地进行此操作 在本例中是每三天一次 还有其他方法可以删除逻辑应用日志 历史记录吗 EDIT 查看
  • NodeJS 模块安装

    我正在尝试在无法访问互联网的计算机上安装 NodeJS 服务器 我复制了 exe 并执行了它 但现在我需要安装几个模块 所以我的问题是 我可以简单地从我的电脑复制模块吗 或者我必须将服务器连接到互联网并使用 npm 吗 编辑 我已经将所有必
  • Java集群中如何最好地进行文件锁定

    我有一个在 JBoss 上运行的服务器集群 我需要以安全的方式更新文件 具体来说 我需要 锁定文件 A 如果它已经被锁定 则以安全的方式阻塞 这样如果 JVM 突然死机 就不会出现悬空锁 30秒的超时就可以了 读取文件A 改变内容 将文件写
  • t 作为 R 中全局变量的名称:不可能吗?

    我想使用 t 作为 R 中全局变量的名称 但它不允许我这样做 sq1 function t lt lt 7 我收到以下错误 Error in sq1 cannot change value of locked binding for t 我
  • 接收信号的 QML 元素失效了?

    我有类似以下的代码 id myComponent signal updateState property variant modelList Repeater model modelList MyButton Connection targ
  • 3D 空间中向量的旋转和方向 - 逆序

    我在 3D 空间中有两个向量 S 开始 和T 目标 我想找到允许这种变换的旋转矩阵 RM 我知道通过计算叉积 S T我得到了旋转轴 之间的角度S and T是 谁 给的tan S T S T where S T is the 点积S 和 T
  • 使用libavcodec解码H264视频,C

    我正在尝试使用 ffmpeg libavcodec 解码原始 h264 文件 但无法使其正常工作 目前输出应该是原始 YUV 文件 可以用GCC编译代码 gcc o decoder decoder c L lib llibavcodec l