2011-12-09 13 views
2

Windows上でx264エンコーダを使用してffmpeg静的ライブラリを構築しようとするとかなりの時間が経過した後、私はいくつかの例を書いています。 もちろん、ビルド方法、使用方法、bla blaについてはたくさんの "説明"があります...しかし、それらはWindows上では動作しません。私はLinuxの人がここでより良い立場にいると思う。今、何百万ドルもの質問は "それは何の目的ですか?" Windows上では役に立たないだけでなく、実際に動作するサードパーティのライブラリを購入することもできました。x264&libavcodec

誰かが「でも、それは動作します!私は言わなければならない、私に働く証拠を与えなさい。私は10fpsで200x100を気にしません。私はそれのためにH264は必要ありません。 1080iフッテージの1秒間の圧縮方法を教えてください。それはH264、それはcrossplatform(あなたが私に尋ねると面白く聞こえる)、Googleはそれを使用しています(それは完璧でなければなりません?)、ここでいくつかの詳細を掘る...

答えて

3

最初に試してみません - あなたはVSを使用する場合は特に - here

からそれを得るその後のシーケンスのようなものです:あなたがencodしたい場合は

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

私はここに投稿する前にほとんど同じことをしました。しかし、私はまだインターレース部分が欠けています。 x264はインターレースフレームを圧縮していることをどのように知っていますか?そして、私がavcodec_encode_video()の後に得たことは、タイムスタンプと戻り値についての警告がゼロであることです。 ffmpegによれば、関数は成功しましたが、ゼロバイトは何も意味しません。 Btw、静的なlibを自分でビルドする必要があります。なぜなら、たまにはバグが見つかるからです。それは常にWindows関連だけです...少なくとも、それは私がソースから伝えることです。 – moose

+0

Btw、私は別のバグを見つけました...あなたが説明したことを正確にやろうとしました。たぶん小さな違いのいくつかは重要です... av_guess_format( "mp4"、szFileName、NULL);無限ループに終わるでしょう。 :-( – moose

+0

avformat_alloc_output_context2()関数と同じ無限ループ動作が発生しますが、とにかく終了しました...バグが多すぎます – moose

0

用libavcodec + libx264をインターレースモードで使用する場合は、CODEC_FLAG_INTERLACED_DCTを使用してください。可能であれば、libx264またはCLIプログラムを直接使うべきですが、それはあまり効果がありません。

関連する問題