jjzjj

c++ - 在 mp4 容器中保存视频时 FPS 太高

coder 2024-02-02 原文

当我从 avi 文件解码帧,然后在 x264 中解码它们并保存到 mp4 文件时,输出文件的 fps 始终是 12,800。因此文件播放速度非常快。但是,当我将编码的 h264 帧保存为 avi 格式而不是 mp4 时,fps 就是我想要的 - 25。

可能是什么问题?

这是我在 VS2010 中编写的代码:

#include "stdafx.h"
#include "inttypes.h"

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

#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
   const char* inFileName = "C:\\000227_C1_GAME.avi";
   const char* outFileName = "c:\\test.avi";
   const char* outFileType = "avi";

   av_register_all();

   AVFormatContext* inContainer = NULL;   
   if(avformat_open_input(&inContainer, inFileName, NULL, NULL) < 0)   
      exit(1);

   if(avformat_find_stream_info(inContainer, NULL) < 0)
      exit(1);

   // Find video stream
   int videoStreamIndex = -1;
   for (unsigned int i = 0; i < inContainer->nb_streams; ++i)
   {
      if (inContainer->streams[i] && inContainer->streams[i]->codec &&
         inContainer->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
      {
         videoStreamIndex = i;
         break;
      }
   }
   if (videoStreamIndex == -1) exit(1);

   AVFormatContext* outContainer = NULL;
   if(avformat_alloc_output_context2(&outContainer, NULL, outFileType, outFileName) < 0)
      exit(1);

   // ---------------------------- 
   // Decoder
   // ---------------------------- 
   AVStream const *const inStream = inContainer->streams[videoStreamIndex];
   AVCodec *const decoder = avcodec_find_decoder(inStream->codec->codec_id);
   if(!decoder) 
      exit(1);
   if(avcodec_open2(inStream->codec, decoder, NULL) < 0) 
      exit(1);

   // ---------------------------- 
   // Encoder
   // ----------------------------             
   AVCodec *encoder = avcodec_find_encoder(AV_CODEC_ID_H264);
   if(!encoder) 
      exit(1);
   AVStream *outStream = avformat_new_stream(outContainer, encoder);      
   if(!outStream)
      exit(1);
   avcodec_get_context_defaults3(outStream->codec, encoder);   

   // Construct encoder
   if(outContainer->oformat->flags & AVFMT_GLOBALHEADER) 
      outStream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;   

   outStream->codec->coder_type = AVMEDIA_TYPE_VIDEO;
   outStream->codec->pix_fmt = AV_PIX_FMT_YUV420P;
   outStream->codec->width = inStream->codec->width;
   outStream->codec->height = inStream->codec->height;
   outStream->codec->codec_id = encoder->id;
   outStream->codec->bit_rate = 500000;
   //outStream->codec->rc_min_rate = 600000;
   //outStream->codec->rc_max_rate = 800000;

   outStream->codec->time_base.den = 25;
   outStream->codec->time_base.num = 1;
   outStream->codec->gop_size = 250; // Keyframe interval(=GOP length). Determines maximum distance distance between I-frames
   outStream->codec->keyint_min = 25; // minimum GOP size
   outStream->codec->max_b_frames = 3;//16; // maximum number of B-frames between non-B-frames
   outStream->codec->b_frame_strategy = 1; // decides the best number of B-frames to use. Default mode in x264.
   outStream->codec->scenechange_threshold = 40;
   outStream->codec->refs = 6; // abillity to reference frames other than the one immediately prior to the current frame. specify how many references can be used.
   outStream->codec->qmin = 0;//10;
   outStream->codec->qmax = 69;//51;
   outStream->codec->qcompress = 0.6;
   outStream->codec->max_qdiff = 4;
   outStream->codec->i_quant_factor = 1.4;//0.71;   

   outStream->codec->refs=1;//3;
   outStream->codec->chromaoffset = -2;
   outStream->codec->thread_count = 1;   
   outStream->codec->trellis = 1;
   outStream->codec->me_range = 16;
   outStream->codec->me_method = ME_HEX; //hex
   outStream->codec->flags2 |= CODEC_FLAG2_FAST;   
   outStream->codec->coder_type = 1;


   if(outStream->codec->codec_id == AV_CODEC_ID_H264)
   {
        av_opt_set(outStream->codec->priv_data, "preset", "slow", 0);
   }

   // Open encoder
   if(avcodec_open2(outStream->codec, encoder, NULL) < 0) 
      exit(1);

   // Open output container
   if(avio_open(&outContainer->pb, outFileName, AVIO_FLAG_WRITE) < 0)
      exit(1);

   //close_o

   AVFrame *decodedFrame = avcodec_alloc_frame();
   if(!decodedFrame) 
      exit(1);
   AVFrame *encodeFrame = avcodec_alloc_frame();
   if(!encodeFrame) 
      exit(1);
   encodeFrame->format = outStream->codec->pix_fmt;
   encodeFrame->width = outStream->codec->width;
   encodeFrame->height = outStream->codec->height;
   if(av_image_alloc(encodeFrame->data, encodeFrame->linesize, 
                 outStream->codec->width, outStream->codec->height, 
                 outStream->codec->pix_fmt, 1) < 0)
      exit(1);

   av_dump_format(inContainer, 0, inFileName,0);

   //Write header to ouput container
   avformat_write_header(outContainer, NULL);

   AVPacket decodePacket, encodedPacket;
   int got_frame, len;
   while(av_read_frame(inContainer, &decodePacket)>=0)
   {      
      if (decodePacket.stream_index == videoStreamIndex)
      {                  
         len = avcodec_decode_video2(inStream->codec, decodedFrame, &got_frame, &decodePacket);
         if(len < 0)
            exit(1);
         if(got_frame)
         {
            av_init_packet(&encodedPacket);
            encodedPacket.data = NULL;
            encodedPacket.size = 0;         
            if(avcodec_encode_video2(outStream->codec, &encodedPacket, decodedFrame, &got_frame) < 0)
               exit(1);
            if(got_frame)
            {
               if (outStream->codec->coded_frame->key_frame)
                  encodedPacket.flags |= AV_PKT_FLAG_KEY;

               encodedPacket.stream_index = outStream->index;

               if(av_interleaved_write_frame(outContainer, &encodedPacket) < 0)
                  exit(1);

               av_free_packet(&encodedPacket);
            }
         }
      }

      av_free_packet(&decodePacket);
   }
   av_write_trailer(outContainer);
   avio_close(outContainer->pb);

   avcodec_free_frame(&encodeFrame);
   avcodec_free_frame(&decodedFrame);

   avformat_free_context(outContainer);
   av_close_input_file(inContainer);
   return 0;
}

最佳答案

问题出在数据包的 PTS 和 DTS 上。在将数据包写入输出之前(在 av_interleaved_write_frame 命令之前)像这样设置 PTS 和 DTS

if (encodedPacket.pts != AV_NOPTS_VALUE)
    encodedPacket.pts =  av_rescale_q(encodedPacket.pts, outStream->codec->time_base, outStream->time_base);
if (encodedPacket.dts != AV_NOPTS_VALUE)
    encodedPacket.dts = av_rescale_q(encodedPacket.dts, outStream->codec->time_base, outStream->time_base);

关于c++ - 在 mp4 容器中保存视频时 FPS 太高,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13565062/

有关c++ - 在 mp4 容器中保存视频时 FPS 太高的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  3. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  4. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  5. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  6. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

    出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

  7. ruby - Ruby 中字符串运算符 + 和 << 的区别 - 2

    我是Ruby和这个网站的新手。下面两个函数是不同的,一个在函数外修改变量,一个不修改。defm1(x)x我想确保我理解正确-当调用m1时,对str的引用被复制并传递给将其视为x的函数。运算符当调用m2时,对str的引用被复制并传递给将其视为x的函数。运算符+创建一个新字符串,赋值x=x+"4"只是将x重定向到新字符串,而原始str变量保持不变。对吧?谢谢 最佳答案 String#+::str+other_str→new_strConcatenation—ReturnsanewStringcontainingother_strconc

  8. ruby - rails 3.2.2(或 3.2.1)+ Postgresql 9.1.3 + Ubuntu 11.10 连接错误 - 2

    我正在使用PostgreSQL9.1.3(x86_64-pc-linux-gnu上的PostgreSQL9.1.3,由gcc-4.6.real(Ubuntu/Linaro4.6.1-9ubuntu3)4.6.1,64位编译)和在ubuntu11.10上运行3.2.2或3.2.1。现在,我可以使用以下命令连接PostgreSQLsupostgres输入密码我可以看到postgres=#我将以下详细信息放在我的config/database.yml中并执行“railsdb”,它工作正常。开发:adapter:postgresqlencoding:utf8reconnect:falsedat

  9. ruby-on-rails - 如何在 Rails 3 中保存到数据库之前格式化值 - 2

    我有一个带有利润字段的用户模型。利润字段是DECIMAL(11,0)类型。我在表单上有一个屏蔽输入,允许用户输入1,000美元之类的内容。我想格式化该值并从中删除除数字以外的所有内容,这样我将保存1000。这是我到目前为止所拥有的:classUser但它一直在数据库中保存0。看起来它在我的格式化函数之前将其转换为十进制。 最佳答案 试试这个:defprofit=(new_profit)self[:profit]=new_profit.gsub(/[^0-9]/,'')end 关于ruby

  10. ruby - 如何以编程方式将 mp3 转换为 itunes 可播放的 aac/m4a 文件? - 2

    我一直在寻找一种以编程方式或通过命令行将mp3转换为aac的方法,但没有成功。理想情况下,我有一段代码可以从我的Rails应用程序中调用,将mp3转换为aac。我安装了ffmpeg和libfaac,并能够使用以下命令创建aac文件:ffmpeg-itest.mp3-acodeclibfaac-ab163840dest.aac当我将输出文件的名称更改为dest.m4a时,它无法在iTunes中播放。谢谢! 最佳答案 FFmpeg提供AAC编码功能(如果您已编译它们)。如果您使用的是Windows,则可以从here获取完整的二进制文件。

随机推荐