首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >x264和libavcodec

x264和libavcodec
EN

Stack Overflow用户
提问于 2011-12-10 07:27:58
回答 2查看 4.6K关注 0票数 2

在尝试使用x264编码器在Windows上构建ffmpeg静态库时,我花了相当多的时间来编写一些示例。当然,有一大堆关于如何构建,如何使用,诸如此类的“说明”。但是,它们都不能在Windows上运行。我猜Linux的人在这里处于更好的位置。现在,数十亿美元的问题是“这一切的目的是什么?”这不仅在Windows上没有用,而且我可以买一些实际有效的第三方库。

如果有人要说“但是,它起作用了!”我必须说,给我一个有效的证明。我不关心10fps下的200x100。我不需要H264来解决这个问题。演示如何压缩一秒的1080i素材。它是H264,它是跨平台的(如果你问我,听起来很有趣),谷歌正在使用它(它必须是完美的,对吧?),还有更多的hipe……

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-12-10 07:37:00

首先,不要尝试在windows上构建--特别是如果你使用VS --从here获取

那么序列是这样的:

代码语言:javascript
复制
 // in ctor
 ffmpeg::avcodec_register_all();   
 ffmpeg::avcodec_init();   
 ffmpeg::av_register_all();

bool createFile(const String &fileName,unsigned int width,unsigned int height,unsigned int fps)
{

   close();

   pFormatCtx=ffmpeg::avformat_alloc_context();
   if(!pFormatCtx)
   {
      printf("Error allocating format context\n");
      return false;
   }


    pOutputFormat = ffmpeg::av_guess_format( "mp4", filename,NULL);


   pFormatCtx->oformat = pOutputFormat;
   _snprintf(pFormatCtx->filename, sizeof(pFormatCtx->filename), "%s",filename);

   // Add the video stream
   pVideoStream = av_new_stream(pFormatCtx,0);
   if(!pVideoStream )
   {
      printf("Could not allocate stream\n");
      return false;
   }


   pCodecCtx=pVideoStream->codec;   
   pCodecCtx->codec_id = pOutputFormat->video_codec;
   pCodecCtx->codec_type = ffmpeg::AVMEDIA_TYPE_VIDEO;


    pCodecCtx->width = Width = width;
    pCodecCtx->height = Height = height;    
    pCodecCtx->time_base.num = 1;
    pCodecCtx->time_base.den = Fps = fps;   
    pCodecCtx->pix_fmt = ffmpeg::PIX_FMT_YUV420P;


    // needed for x264 to work
     pCodecCtx->me_range = 16;
     pCodecCtx->max_qdiff = 4;
     pCodecCtx->qmin = 10;
     pCodecCtx->qmax = 51;
     pCodecCtx->qcompress = 0.6;
     pCodecCtx->gop_size = 12;




    avcodec_thread_init(pCodecCtx, 10);


   // some formats want stream headers to be separate
   if(pFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)
      pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;


   if (av_set_parameters(pFormatCtx, NULL) < 0)
   {
      printf("Invalid output format parameters\n");
      return false;
   }

   ffmpeg::dump_format(pFormatCtx, 0, pFormatCtx->filename, 1);

   // open_video
   // find the video encoder
   pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
   if (!pCodec)
   {
      printf("codec not found\n");
      return false;
   }
   // open the codec
   if (avcodec_open(pCodecCtx, pCodec) < 0)
   {
      printf("could not open codec\n");
      return false;
   }

   // Allocate memory for output
   if(!initOutputBuf())
   {
      printf("Can't allocate memory for output bitstream\n");
      return false;
   }

   // Allocate the YUV frame
   if(!initFrame())
   {
      printf("Can't init frame\n");
      return false;
   }

   if (url_fopen(&pFormatCtx->pb,pFormatCtx->filename, URL_WRONLY) < 0)
   {
      printf( "Could not open '%s'\n", pFormatCtx->filename);
      return false;
   }


    av_write_header(pFormatCtx);

   return true;
}

然后,对于每个帧

代码语言:javascript
复制
int encodeImage(const QImage &img)
{

   if (!convertImage_sws(img)) {     // SWS conversion
       return false;
   }


   ppicture->pts=pCodecCtx->frame_number;

   //memset(outbuf,0,outbuf_size);
   int out_size = ffmpeg::avcodec_encode_video(pCodecCtx,outbuf,outbuf_size,ppicture);

   if (out_size > 0)   {
        ffmpeg::AVPacket pkt; 
        av_init_packet(&pkt);


      if (pCodecCtx->coded_frame->pts != (0x8000000000000000LL))
         pkt.pts= av_rescale_q(pCodecCtx->coded_frame->pts, pCodecCtx->time_base, pVideoStream->time_base);

      if(pCodecCtx->coded_frame->key_frame)
         pkt.flags |= AV_PKT_FLAG_KEY;

      pkt.stream_index= pVideoStream->index;
      pkt.data= outbuf;
      pkt.size= out_size;      
      if (av_write_frame(pFormatCtx, &pkt) < 0 ) {        
          return 0;
      }           
   }

   return out_size;
}

void close()
{

   av_write_trailer(pFormatCtx);

   // close_video
   avcodec_close(pVideoStream->codec);
   freeFrame();
   freeOutputBuf();


   /* free the streams */
   for(int i = 0; i < pFormatCtx->nb_streams; i++)
   {
      av_freep(&pFormatCtx->streams[i]->codec);
      av_freep(&pFormatCtx->streams[i]);
   }

   // Close file
   url_fclose(pFormatCtx->pb);

   // Free the stream
   av_free(pFormatCtx);

}


bool initFrame()
{
   ppicture = ffmpeg::avcodec_alloc_frame();
   if(ppicture==0)
      return false;

   int size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
   picture_buf = new uint8_t[size];
   if(picture_buf==0)
   {
      av_free(ppicture);
      ppicture=0;
      return false;
   }

   // Setup the planes
   avpicture_fill((ffmpeg::AVPicture *)ppicture, picture_buf,pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);

   ppicture->pts = 0;
   return true;
}
票数 3
EN

Stack Overflow用户

发布于 2012-01-25 11:14:56

如果要在隔行扫描模式下使用libavcodec+libx264进行编码,请使用CODEC_FLAG_INTERLACED_DCT。如果可能,您应该直接使用libx264或CLI程序,这样做的工作量会更少。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8452985

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档