2

Windows で x264 エンコーダーを使用して ffmpeg 静的ライブラリーをビルドしようとしてかなりの時間を費やした後、それを使用していくつかの例を作成するためにさらに時間を費やしました。もちろん、ビルド方法、使用方法、ブラブラについての「説明書」は山ほどありますが、Windows ではそれらのどれも機能しません。ここでは、Linux の方が有利な立場にあると思います。さて、莫大な金額の質問は、「そのすべての目的は何ですか?」です。これは Windows では役に立たないだけでなく、実際に動作するサード パーティのライブラリを購入することもできたはずです。

誰かが「でも、うまくいく!」と言おうとしている場合。私は言わなければならない、私に働く証拠をください。10fpsで200x100は気にしません。そのためにH264は必要ありません。1 秒間の 1080i 映像を圧縮する方法を教えてください。それは H264 であり、クロスプラットフォームであり (私に尋ねると変に聞こえます)、Google はそれを使用しています (完璧でなければなりませんよね?)、ここでいくつかのハイプ...

4

2 に答える 2

3

まず、Windows でビルドしようとしないでください。特に VS を使用している場合は、ここから入手してください。

次に、シーケンスは次のようになります。

 // 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;
}

次に、フレームごとに

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;
}
于 2011-12-09T23:36:59.800 に答える
0

インターレースモードでlibavcodec+libx264を使用してエンコードする場合は、を使用しますCODEC_FLAG_INTERLACED_DCT。可能であれば、libx264またはCLIプログラムを直接使用する必要がありますが、作業量は少なくなります。

于 2012-01-25T03:14:56.227 に答える