2016-03-21 11 views
1

dranger.comのチュートリアルを使用して画像をデコードしようとしています。以下は、私が作業しているコードです。このコードは、のpgm_save()関数と、廃止された関数を置き換えるだけでなく、ほとんど変更されていません。FFmpegでビデオフレームをデコードするときに裂けた画像

プログラムが正常にコンパイルが、私はビデオを処理しようとしたとき、私はこのような効果引き裂く取得しています:image1とこのimage2を。

(サイド質問:私は(avpicture_fillを交換しようとしました)av_image_copy_to_buffer()で推奨されていませんが、存在する場合、私は疑問に思う私がアクセス違反エラーを取得していますので、あるとして、私はそれを残しました。フレームデータをバッファに割り当てる適切な方法です)。

私が使用しているライブラリは、ffmpeg-20160219-git-98a0053-win32-devです。誰かが私にこれを手伝ってもらえると本当に感謝します。

// Decode video and save frames 

char filename[] = "test%0.3d.ppm"; 
static void ppm_save(unsigned char *buf, int wrap, int xsize, int ysize, 
        int framenum) 
{ 

    char filenamestr[sizeof(filename)]; 
    FILE *f; 
    int i; 

    sprintf_s(filenamestr, sizeof(filenamestr), filename, framenum); 
    fopen_s(&f,filenamestr,"w"); 
    fprintf(f,"P6\n%d %d\n%d\n",xsize,ysize,255); 
    for(i=0;i<ysize;i++) 
     fwrite(buf + i * wrap,1,xsize*3,f); 
    fclose(f); 
} 



int main(int argc, char** argv) 
{ 

    AVFormatContext *pFormatCtx = NULL; 
    AVCodecContext *codecCtx= NULL; 
    AVCodec *codec; 

    int videoStream; 
    int frameFinished; 
    AVFrame *inframe; 
    AVFrame *outframe; 

    struct SwsContext *sws_ctx = NULL; 

    AVPacket avpkt; 
    unsigned int i; 



    printf("Video decoding application\n"); 

    // Register all formats and codecs 
    av_register_all(); 

    // Open video file 
    if (avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) != 0) 
     return -1; // Couldn't open file 

    // Retrieve stream information 
    if (avformat_find_stream_info(pFormatCtx, NULL) < 0) 
     return -1; // Couldn't find stream information 

    // Dump information about file onto standard error (Not necessary) 
    av_dump_format(pFormatCtx, 0, argv[1], 0); 

    // Find the first video stream 
    videoStream = -1; 
    for (i = 0; i < pFormatCtx->nb_streams; i++) 
     if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { 
      videoStream = i; 
      break; 
     } 
    if (videoStream == -1) 
     return -1; // Didn't find a video stream 

    /* find the video decoder */ 
    codec = avcodec_find_decoder(pFormatCtx->streams[videoStream]->codec->codec_id); 
    if (!codec) { 
     fprintf(stderr, "codec not found\n"); 
     exit(1); 
    } 

    codecCtx= avcodec_alloc_context3(codec); 
    if(avcodec_copy_context(codecCtx, pFormatCtx->streams[i]->codec) != 0) { 
     fprintf(stderr, "Couldn't copy codec context"); 
     return -1; // Error copying codec context 
    } 

    /* open it */ 
    if (avcodec_open2(codecCtx, codec, NULL) < 0) { 
     fprintf(stderr, "could not open codec\n"); 
     exit(1); 
    } 

    // Allocate video frame 
    inframe= av_frame_alloc(); 
    if(inframe==NULL) 
     return -1; 

    // Allocate output frame 
    outframe=av_frame_alloc(); 
    if(outframe==NULL) 
     return -1; 

    // Determine required buffer size and allocate buffer 
    int numBytes=av_image_get_buffer_size(AV_PIX_FMT_RGB24, codecCtx->width, 
        codecCtx->height,1); 
    uint8_t* buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); 

    // Assign appropriate parts of buffer to image planes in outframe 
    // Note that outframe is an AVFrame, but AVFrame is a superset 
    // of AVPicture 


    avpicture_fill((AVPicture *)outframe, buffer, AV_PIX_FMT_RGB24, 
     codecCtx->width, codecCtx->height); 
    //av_image_copy_to_buffer(buffer, numBytes, 
//       outframe->data, outframe->linesize, 
//       AV_PIX_FMT_RGB24, codecCtx->width, codecCtx->height,1); 

    // initialize SWS context for software scaling 
    sws_ctx = sws_getContext(codecCtx->width, 
       codecCtx->height, 
       codecCtx->pix_fmt, 
       codecCtx->width, 
       codecCtx->height, 
       AV_PIX_FMT_RGB24, 
       SWS_BILINEAR, 
       NULL, 
       NULL, 
       NULL 
       ); 


    // av_init_packet(&avpkt); 


    i = 0; 
    while(av_read_frame(pFormatCtx, &avpkt)>=0) { 
     // Is this a packet from the video stream? 
     if(avpkt.stream_index==videoStream) { 
      // Decode video frame 
      avcodec_decode_video2(codecCtx, inframe, &frameFinished, &avpkt); 

      // Did we get a video frame? 
      if(frameFinished) { 
     // Convert the image from its native format to RGB 
     sws_scale(sws_ctx, (uint8_t const * const *)inframe->data, 
       inframe->linesize, 0, codecCtx->height, 
       outframe->data, outframe->linesize); 

     // Save the frame to disk 
     if(++i%15 == 0) 
      ppm_save(outframe->data[0], outframe->linesize[0], 
         codecCtx->width, codecCtx->height, i); 

      } 
     } 

    // Free the packet that was allocated by av_read_frame 
    av_packet_unref(&avpkt); 
    } 


    // Free the RGB image 
    av_free(buffer); 
    av_frame_free(&outframe); 

    // Free the original frame 
    av_frame_free(&inframe); 

    // Close the codecs 
    avcodec_close(codecCtx); 
    av_free(codecCtx); 

    // Close the video file 
    avformat_close_input(&pFormatCtx); 


    printf("\n"); 


    return 0; 
} 

答えて

1

解決済み。問題はのpgm_save()機能にあります。バイナリデータを書き込んでいるときにファイルをテキストファイルとして開いていました。正しいモードは"wb"ではなく、"w"である必要があります。

正しいコードがされている必要があります:それは、私は問題は、すべての後にffmpegのために無関係であることに気づいた今愚かな感じ

// fopen_s(&f,filenamestr,"w"); // text mode 
fopen_s(&f,filenamestr,"wb"); // binary mode 

。明るい面では、少なくとも私はコードが動作することを知っています。 ;-)

関連する問題