2016-03-21 5 views
1

erfasst wurden Ich versuche, die Bilder mit dem Tutorial bei dranger.com zu entschlüsseln. Unten ist der Code, mit dem ich arbeite. Der Code ist ziemlich unberührt von pgm_save() Funktion und ersetzt die veralteten Funktionen.Zerrissene Bilder, die beim Entschlüsseln von Videobildern mit FFmpeg

Das Programm erfolgreich kompiliert, aber als ich versuchte, ein Video zu verarbeiten, bekomme ich Tearing-Effekt wie folgt: image1 und dies image2.

(Side Frage: Ich habe versucht, avpicture_fill() zu ersetzen, die mit av_image_copy_to_buffer veraltet ist() aber ich bin eine Zugriffsverletzung Fehler bekommen, so dass ich ließ es wie ich frage mich, ob es gibt. ein geeigneter Weg für mich, die Rahmendaten einem Puffer zuzuweisen.)

Die Bibliothek, die ich verwende, ist ffmpeg-20160219-git-98a0053-win32-dev. Würde es wirklich schätzen, wenn mir jemand dabei helfen könnte.

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

Antwort

1

Gelöst. Das Problem liegt in der pgm_save() Funktion. Ich habe die Datei als eine Textdatei geöffnet, als ich binäre Daten schrieb. Der korrekte Modus sollte "wb" nicht "w" sein.

Der richtige Code hätte sein müssen:

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

Es dumm fühlt sich jetzt, dass ich erkannt, dass das Problem nicht verwandt ist, nachdem alle ffmpeg. Zumindest weiß ich jetzt, dass der Code funktioniert. ;-)

Verwandte Themen