为什么从 avi 容器解码帧并将其编码为 h264/mp​​4 不起作用?

2023-11-25

我开始使用 ffmpeg,我想将 avi 文件转换为 mp4/h264 文件。我读过很多帖子,包括this,但我找不到任何好的示例如何将帧保存到 mp4 文件。下面的代码是简化的代码,它从 avi 文件中解码帧并将其编码为 H264/mp​​4 文件,但是当我保存帧时,mp4 文件无法播放。我认为我在编码方面做错了一些事情

如果您能告诉我出了什么问题以及如何解决它,我将不胜感激。

const char* aviFileName = "aviFrom.avi";
const char* mp4FileName = "mp4To.mp4";

// Filling pFormatCtx by open video file and Retrieve stream information
// ...
// Retrieving codecCtxDecode and opening codecDecode 
//...


// Get encoder
codecCtxEncode = avcodec_alloc_context();   
codecCtxEncode->qmax = 69; 
codecCtxEncode->max_qdiff = 4;
codecCtxEncode->bit_rate = 400000;
codecCtxEncode->width = codecCtxDecode->width;
codecCtxEncode->height = codecCtxDecode->height;
codecCtxEncode->pix_fmt = AV_PIX_FMT_YUV420P;   
codecEncode = avcodec_find_encoder(CODEC_ID_H264);
if(codecEncode == NULL)
    return -1;  
if(avcodec_open2(codecCtxEncode, codecEncode, NULL))
    return -1;

SwsContext *sws_ctx = sws_getContext(codecCtxDecode->width, codecCtxDecode->height, codecCtxDecode->pix_fmt,
                            codecCtxDecode->width, codecCtxDecode->height, AV_PIX_FMT_YUV420P,
                            SWS_BILINEAR, NULL, NULL, NULL);

// Allocate an AVFrame structure    
frameDecoded = avcodec_alloc_frame();
frameEncoded = avcodec_alloc_frame();    

avpicture_alloc((AVPicture *)frameEncoded, AV_PIX_FMT_YUV420P, codecCtxDecode->width, codecCtxDecode->height);

while(av_read_frame(pFormatCtx, &packet)>=0)
{       
    // Is this a packet from the video stream?
    if(packet.stream_index==videoStreamIndex) {
        avcodec_decode_video2(codecCtxDecode, frameDecoded, &frameFinished, &packet);
        // Did we get a video frame?
        if(frameFinished)
        {           
            fwrite(packet.data, packet.size,
            sws_scale(sws_ctx, frameDecoded->data, frameDecoded->linesize, 0, codecCtxDecode->height, 
                        frameEncoded->data, frameEncoded->linesize);



            int64_t pts = packet.pts;
            av_free_packet(&packet);
            av_init_packet(&packet);
            packet.data = NULL;
            packet.size = 0;    
            frameEncoded->pts = pts;                

            int failed = avcodec_encode_video2(codecCtxEncode, &packet, frameEncoded, &got_output);
            if(failed)
            {
                exit(1);
            }
            fwrite(packet.data,1,packet.size, mp4File);
        }
    }

    av_free_packet(&packet);
}

您必须使用 ffmpeg 输出上下文,而不是直接写入原始数据包。

您需要执行的基本步骤:

// find output format
AVOutputFormat * outputFormat = av_guess_format("mp4", NULL, NULL);
AVFormatContext *outFmtCtx = NULL;

// create output cotext
avformat_alloc_output_context2(&outFmtCtx, outputFormat, NULL, NULL);

// create new stream
AVStream * outStrm = avformat_new_stream(outFmtCtx, codecEncode);
avcodec_get_context_defaults3(outStrm->codec, *codec);

outStrm->codec->codec_id = codec_id;
outStrm->codec->coder_type = AVMEDIA_TYPE_VIDEO;
/// outStrm->codec-> ... 
/// set all fields marked as "MUST be set by user" in avcodec.h
/// ....

// create file
avio_open2(&outFmtCtx->pb, file_name, AVIO_FLAG_WRITE, NULL, NULL);
avformat_write_header(outFmtCtx, NULL);

/// write packets
/// for ( )
av_interleaved_write_frame(outFmtCtx, packet);

/// finish
av_write_trailer(outFmtCtx);
avio_close(outFmtCtx->pb);
avformat_free_context(outFmtCtx);

UPD:复制视频而不重新编码的完整代码:

extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
}

int main(int argc, char* argv[])
{
    const char * kInputFileName = "f:/Projects/Temp/testFFMPEG2/test/test_in.avi";
    const char * kOutputFileName = "f:/Projects/Temp/testFFMPEG2/test/text_out.avi";
    const char * kOutputFileType = "avi";

    av_register_all();

    AVFormatContext * inCtx = NULL;
    int err = avformat_open_input(&inCtx, kInputFileName, NULL, NULL);
    if (err < 0)
        exit(1);

    err = av_find_stream_info(inCtx);
    if (err < 0)
        exit(1);


    int vs = -1;
    for (unsigned int s = 0; s < inCtx->nb_streams; ++s)
    {
        if (inCtx->streams[s] &&
            inCtx->streams[s]->codec &&
            inCtx->streams[s]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            vs = s;
            break;
        }        
    }

    if (vs == -1)
        exit(1);

    AVOutputFormat * outFmt = av_guess_format(kOutputFileType, NULL, NULL);
    if (!outFmt)
        exit(1);

    AVFormatContext *outCtx = NULL;
    err = avformat_alloc_output_context2(&outCtx, outFmt, NULL, NULL);

    if (err < 0 || !outCtx)
        exit(1);

    AVStream * outStrm = av_new_stream(outCtx, 0);
    AVStream const * const inStrm = inCtx->streams[vs];
    AVCodec * codec = NULL;
    avcodec_get_context_defaults3(outStrm->codec, codec);
    outStrm->codec->thread_count = 1;

#if (LIBAVFORMAT_VERSION_MAJOR == 53)
    outStrm->stream_copy = 1;
#endif

    outStrm->codec->coder_type = AVMEDIA_TYPE_VIDEO;
    if(outCtx->oformat->flags & AVFMT_GLOBALHEADER) 
        outStrm->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;

    outStrm->codec->sample_aspect_ratio = outStrm->sample_aspect_ratio = inStrm->sample_aspect_ratio; 

#if (LIBAVFORMAT_VERSION_MAJOR == 53)
    outCtx->timestamp = 0;
#endif

    err = avio_open(&outCtx->pb, kOutputFileName, AVIO_FLAG_WRITE);
    if (err < 0)
        exit(1);

#if (LIBAVFORMAT_VERSION_MAJOR == 53)
    AVFormatParameters params = {0};
    err = av_set_parameters(outCtx, &params);
    if (err < 0)
        exit(1);
#endif

    outStrm->disposition = inStrm->disposition;
    outStrm->codec->bits_per_raw_sample = inStrm->codec->bits_per_raw_sample;
    outStrm->codec->chroma_sample_location = inStrm->codec->chroma_sample_location;
    outStrm->codec->codec_id = inStrm->codec->codec_id;
    outStrm->codec->codec_type = inStrm->codec->codec_type;

    if (!outStrm->codec->codec_tag)
    {
        if (! outCtx->oformat->codec_tag
            || av_codec_get_id (outCtx->oformat->codec_tag, inStrm->codec->codec_tag) == outStrm->codec->codec_id
            || av_codec_get_tag(outCtx->oformat->codec_tag, inStrm->codec->codec_id) <= 0)
                    outStrm->codec->codec_tag = inStrm->codec->codec_tag;
    }

    outStrm->codec->bit_rate = inStrm->codec->bit_rate;
    outStrm->codec->rc_max_rate = inStrm->codec->rc_max_rate;
    outStrm->codec->rc_buffer_size = inStrm->codec->rc_buffer_size;

    const size_t extra_size_alloc = (inStrm->codec->extradata_size > 0) ?
                                    (inStrm->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE) :
                                     0;

    if (extra_size_alloc)
    {
        outStrm->codec->extradata = (uint8_t*)av_mallocz(extra_size_alloc);    
        memcpy( outStrm->codec->extradata, inStrm->codec->extradata, inStrm->codec->extradata_size);
    }
    outStrm->codec->extradata_size = inStrm->codec->extradata_size;

    AVRational input_time_base = inStrm->time_base;
    AVRational frameRate = {25, 1};
    if (inStrm->r_frame_rate.num && inStrm->r_frame_rate.den 
        && (1.0 * inStrm->r_frame_rate.num / inStrm->r_frame_rate.den < 1000.0))
    {
        frameRate.num = inStrm->r_frame_rate.num;
        frameRate.den = inStrm->r_frame_rate.den;
    }

    outStrm->r_frame_rate = frameRate;
    outStrm->codec->time_base = inStrm->codec->time_base;

    outStrm->codec->pix_fmt = inStrm->codec->pix_fmt;
    outStrm->codec->width =  inStrm->codec->width;
    outStrm->codec->height =  inStrm->codec->height;
    outStrm->codec->has_b_frames =  inStrm->codec->has_b_frames;
    if (! outStrm->codec->sample_aspect_ratio.num) {
        AVRational r0 = {0, 1};
        outStrm->codec->sample_aspect_ratio =
            outStrm->sample_aspect_ratio =
            inStrm->sample_aspect_ratio.num ? inStrm->sample_aspect_ratio :
            inStrm->codec->sample_aspect_ratio.num ?
            inStrm->codec->sample_aspect_ratio : r0;
    }
#if LIBAVFORMAT_VERSION_MAJOR == 53
    av_write_header(outFmtCtx);
#else
    avformat_write_header(outCtx, NULL);
#endif


    for (;;)
    {
        AVPacket packet = {0};
        av_init_packet(&packet);

        err = AVERROR(EAGAIN);
        while (AVERROR(EAGAIN) == err) 
            err = av_read_frame(inCtx, &packet);

        if (err < 0)
        {
            if (AVERROR_EOF != err && AVERROR(EIO) != err)
            {
                // error
                exit(1);            
            }
            else
            {
                // end of file
                break;
            }            
        }


        if (packet.stream_index == vs)
        {

            err = av_interleaved_write_frame(outCtx, &packet);
            if (err < 0)
                exit(1);
        }            

        av_free_packet(&packet);        

    }

    av_write_trailer(outCtx);
    if (!(outCtx->oformat->flags & AVFMT_NOFILE) && outCtx->pb)
        avio_close(outCtx->pb);

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

为什么从 avi 容器解码帧并将其编码为 h264/mp​​4 不起作用? 的相关文章

  • 为 iOS6.0 ARMv7 处理器构建 FFMPEG 库

    WARNING 我刚刚被另一位用户告知 在 iOS 上使用 FFMPEG 存在一些法律问题 请在此处留下链接http multinc com 2009 08 24 compatibility Between the iphone app s
  • ffmpeg 使用 -movflags faststart

    我尝试使用命令 movflags 快速启动 并得到以下错误 Microsoft Windows 版本 6 0 6002 版权所有 c 2006 Microsoft 公司 版权所有 C uploads 1 videos gt ffmpeg i
  • HTML 5 视频拉伸

    您能让视频 拉伸 到视频元素的宽度和高度吗 显然 默认情况下 视频会按比例缩放并适合视频元素 thanks 我已经使用 object fit fill in CSS 进行了测试 效果很好 video object fit fill 来自 M
  • 使用 jQuery 将播放/暂停/结束功能绑定到 HTML5 视频

    我正在尝试绑定play pause and ended使用 jQuery 的事件但有一个问题 当我右键单击视频并选择播放或暂停时 图标会正确更改 当我单击播放按钮时 它会更改为暂停 但如果我单击暂停按钮继续播放视频 它不会更改为再次播放 谁
  • 如何使用ijkplayer库

    我要使用 ijkplayergithub链接 https github com bbcallen ijkplayer 我下载了这个 然后通过 文件 gt 导入 gt 常规 gt 现有项目到工作区 将其导入到 eclipse 中 之后我有三个
  • 使用 Servlet 启动 VLC HTTP Stream 时出现问题

    我正在为自己开发一个 VLC 项目 我的目标是创建一个 HTML 前端来启动流 我通过使用 Java Servlet 来完成此操作 概述 乌班图13 04 Java 7 21 冰茶 2 3 9 Eclipse JAVAEE IDE 雄猫7
  • 视频作为网站背景? HTML 5

    我想使用视频作为背景 而不是自动拉伸到整个屏幕 背景 的图像 我还想旋转视频和图像 以便以任何顺序显示随机视频 图像 如果知道如何延迟视频播放 以便视频在网站加载后 30 秒只播放一次 那就太好了 thx 看看我的 jquery video
  • 使用 ffmpeg 在纯色背景上叠加延时视频

    我有很多名为的主页屏幕截图homescreen000001 png homescreen000002 png等 我正在尝试使用 ffmpeg 创建这些图像的延时视频 当我运行以下命令时 它通常可以正常工作 ffmpeg f image2 i
  • 加载视频数据集(Keras)

    我正在尝试实现 LRCN C LSTM RNN 来对视频中的情绪进行分类 我的数据集结构分为两个文件夹 train set 和 valid set 当你打开其中任何一个时 你可以找到3个文件夹 积极 消极 和 惊喜 最后 这 3 个文件夹中
  • HTML 5

    尽管开放视频标准似乎处于某种危险之中 但它是一个好主意 我看到了一些关于运动跟踪的演示 只是概念验证 但仍然很有趣 现在 我想说像这样的概念really如果能够访问用户的网络摄像头 这将是一种收获 想象一下 双手举在半空中浏览 Flickr
  • ffmpeg通过添加框或边框来扩展(而不是调整大小)视频大小

    假设我有一个特殊分辨率的视频 例如 1280x718 我想将其更改为 1280x720 但我宁愿只在顶部和底部添加一行 而不是将 718 像素垂直插值到 720 所以基本上 我正在寻找一种方法告诉 ffmpeg 创建 1280x720 的输
  • VideoJs 在 Firefox 中的 Flash 回退问题

    我尝试将 videoJs 添加到我的网站来播放 MP4 文件 所有这些在 Chrome 中都能完美运行 但当我转到 Firefox 不支持 MP4 文件 时 Flash 播放器停留在黑屏上 按钮不执行任何操作 简单的问题 为什么 我不明白
  • 如何使用 AVFoundation 组合不同方向的视频剪辑

    我正在尝试使用 AVFoundation 将多个视频剪辑合并为一个 我可以使用下面的代码使用 AVMutableComposition 创建单个视频 AVMutableComposition composition AVMutableCom
  • FFmpeg - H264 编码器找不到有效设备并且无法配置编码器

    我尝试使用 H264 编码器进行编码 但是当我这样做时 出现以下错误 h264 v4l2m2m 0x55682d2416c0 Could not find a valid device h264 v4l2m2m 0x55682d2416c0
  • flash/flex:渐进式下载与 rtmp

    我试图理解并真正确定何时在 Flex flash 中使用渐进式下载与 rtmp 看来主要的一点是 rtmp 不与 http 一起提供服务 而渐进式下载则由 http 提供 由于它不是 rtmp 因此资源受到保护 因为无法从 swf 外部连接
  • 使用 AVFoundation 快速获取视频帧

    这是我的代码 我想要获取我的视频并将帧数据获取到 SceneKit SCNSphere NSString videoPath NSBundle mainBundle l var videoURL NSBundle mainBundle UR
  • 仅使用 url 嵌入视频

    给定一个 youtube url 我如何使用 net c 将视频嵌入到页面中 只需添加如下一行 将 autoplay 设置为 0 或 1 取决于您是否希望人们真正留在您的页面上
  • 视频流上的 TCP 与 UDP

    我刚从网络编程考试回来 他们问我们的问题之一是 如果您要传输视频 您会使用 TCP 还是 UDP 请解释一下存储视频和实时视频流 对于这个问题 他们只是希望得到一个简短的答案 TCP 用于存储视频 UDP 用于实时视频 但我在回家的路上想到
  • Google Cloud Platform:将上传的 MP4 文件转换为 HLS 文件

    我正在构建一个平台 允许用户将一些视频文件 20 40 秒 从手机上传到服务器 所有这些上传目前都运行良好 文件通过nodejs云功能存储在谷歌存储桶中 现在我想创建一个 gcp 转码器作业 它将上传的 mp4 视频文件转换为 hls 视频
  • AVFoundation (AVPlayer) 支持的格式?没有 .vob 或 .mpg 容器?

    在 Mac 应用程序中使用 AVPlayer 可以全屏播放文件夹中的随机视频 但当我尝试播放 vob 文件或 mpg 文件时 我只会看到黑屏 黑屏的持续时间与视频持续时间一样长 AVFoundation 不支持从这些容器播放吗 我认为既然它

随机推荐

  • 如何确定是否由于共享冲突而引发 IOException?

    我有一个 C 应用程序 我想将文件复制到新位置 有时我需要覆盖现有文件 当发生这种情况时 我收到 System IO IOException 我想从共享冲突中恢复 但如何确定返回 IOException 是因为目标文件正在使用而不是其他原因
  • ggmap中的动态数据点标签定位

    我正在使用 R 中的 ggmap 包 并且对地理空间数据可视化相对较新 我有一个由十一个纬度和经度对组成的数据框 我想将其绘制在地图上 每个纬度和经度对都有一个标签 这是虚拟数据 lat lt c 47 597157 47 656322 4
  • 在发现“EntityFrameworkConfiguration”类型之前使用默认的 DbConfiguration 实例

    public class EntityFrameworkConfiguration DbConfiguration public EntityFrameworkConfiguration this SetModelCacheKey ctx
  • Google Pub/Sub 的 RetryPolicy 中配置的指数退避如何工作?

    The cloud google com go pubsub最近发布的库 在 v1 5 0 中 参见https github com googleapis google cloud go releases tag pubsub 2Fv1 5
  • 我可以重命名 numpy 记录数组中的字段吗

    我是 python 新手 所以这听起来可能很基础 我已经使用 csv2rec 导入了 csv 文件 第一行有标题 我想将标题更改为 x y z 这样做的最佳方法是什么 gt gt gt import matplotlib gt gt gt
  • Cython 中的内存视图排序

    如何在 Cython 中对内存视图进行就地排序 有没有内置函数可以做到这一点 现在我必须使用numpy数组代替并使用numpy的排序 这非常慢 为了跟进我的评论 这里有 3 个选项 numpy 和 C 和 C 标准库选项 from libc
  • 在seaborn中绘制回归时如何获得数值拟合结果

    If I use the seaborn library in Python to plot the result of a linear regression is there a way to find out the numerica
  • 未针对 Windows 配置 DefaultFirebaseOptions

    错误 flutter lib ui ui dart state cc 198 未处理的异常 不受支持的操作 尚未为 Windows 配置 DefaultFirebaseOptions 您可以通过再次运行 FlutterFire CLI 来重
  • 查找并替换字符串

    是否可以在页面加载之前查看页面的源代码 找到某个部分并将其替换为其他内容 我想使用 JavaScript 来完成此操作 以便我可以在 Chrome 扩展中使用它 所以像这样 找到 google com 替换为 yahoo com
  • 如何使用jquery联系叔叔

    div div div div div div 我在 me 我想选择我的叔叔 使用如下内容 me find uncle me next uncle me prev uncle How 你可以使用 parent and prev假设你的叔叔总
  • Visual Studio 2008 插件/加载项开发 - 入门

    和 关联这个计算器问题 我将如何创建自己的 Visual Studio 2008 插件 我查看了 MSDN 上的 Visual Studio 开发人员中心 但信息量巨大 项目类型繁多 我什至不知道从哪里开始 我应该从哪里开始寻找如果我想写一
  • na.locf 但不执行尾随 NA

    我有以下时间序列 gt y lt xts 1 10 Sys Date 1 10 gt y c 1 2 5 9 10 lt NA gt y 1 2011 09 04 NA 2011 09 05 NA 2011 09 06 3 2011 09
  • 如何在 Delphi 中以编程方式创建带有几个组件的表单

    我正在使用 Delphi 7 并尝试以编程方式创建表单 这是我的表单类存根 unit clsTStudentInfoForm interface uses Forms type TStudentInfoForm class TForm en
  • 为什么操作系统在内存足够的情况下却说无法给jvm分配内存

    我正在尝试使用以下命令启动一个新的 jvm java version 但是报错 There is insufficient memory for the Java Runtime Environment to continue Native
  • socket.io 套接字 ID 应该保密吗?

    我正在使用 socket io 开发一个 Web 应用程序 我目前正在使用套接字 ID 作为标识符 该标识符会广播给其他客户端 现在 这引发了安全问题 即该 ID 是否可用于劫持另一个用户会话 不幸的是 在网上很难找到这方面的任何信息 那么
  • 为什么分配给空列表(例如 [] = "")不会出错?

    在 python 3 4 中 我正在输入 并且它工作正常 没有引发异常 虽然当然 不等于 然后 也工作正常 但正如预期的那样引发了异常 但正如预期的那样引发了异常 发生什么了 你不是为了平等而比较 你是指派 Python 允许您分配给多个目
  • iOS模拟器不播放声音[重复]

    这个问题在这里已经有答案了 在 XCode 6 上 设备上一切正常 但在模拟器上 无法播放声音 这是我的快速代码 var url NSURL string http my url com sound mp3 var data NSData
  • 如何在 MySQL 数据库中存储 JSON 字符串

    我使用下面的代码将 JSON 数据存储在 MySQL 表中 如果 JSON 很短 它可以正常工作 但如果文本较长 则会中断 field json 是一个长文本 sql sprintf UPDATE mytable SET field jso
  • C# 获取控件在窗体上的位置

    当控件可能位于其他控件 如面板 内部时 是否有任何方法可以检索控件在表单中的位置 该控件的 Left 和 Top 属性只提供了它在其父控件中的位置 但是如果我的控件位于五个嵌套面板内 并且我需要它在窗体上的位置 该怎么办 快速示例 按钮 b
  • 为什么从 avi 容器解码帧并将其编码为 h264/mp​​4 不起作用?

    我开始使用 ffmpeg 我想将 avi 文件转换为 mp4 h264 文件 我读过很多帖子 包括this 但我找不到任何好的示例如何将帧保存到 mp4 文件 下面的代码是简化的代码 它从 avi 文件中解码帧并将其编码为 H264 mp