2014-06-05 24 views
8

Ben gelişmekte FFmpeg'den girmek istiyorum) (av_frame_alloc ve ben bu örnekler burada öğretici takip etmeye başladı: İlk öğretici ile başladı hereFFmpeg: tanımsız başvurular

- tutorial01.c - ama bu soruna 'girmek av_frame_alloc() 'için tanımlanmamış başvurular.

Ubuntu'da yaşıyorum 12.04 LTS.

/* 
* File: main.c 
* Author: dontrythisathome 
* 
* Created on 3 giugno 2014, 23.02 
*/ 

#include <stdio.h> 
#include <libavcodec/avcodec.h> 
#include <libavformat/avformat.h> 
#include <libavutil/frame.h> 
#include <libswscale/swscale.h> 
/* 
* 
*/ 
void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) 
    { 
     FILE *pFile; 
     char szFilename[32]; 
     int  y; 

     //Apre il file 
     sprintf(szFilename, "frame%d.ppm", iFrame); 
     pFile=fopen(szFilename, "wb"); 
     if(pFile==NULL) 
     {return; } 

     //Scrive l'intestazione del file (Larghezza x Altezza su video) 
     fprintf(pFile, "P6\n%d %d\n255\n", width, height); 

     //Scrive i data pixel 
     for(y=0; y<height; y++) 
     { 
      fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile); 
     } 

     //Chiude il file 
     fclose(pFile); 
     } 
/* 
* 
*/ 
/*Main Function*/ 
int main(int argc, char *argv[]) 
{ 
    AVFormatContext *pFormatCtx; 
    int          i, videoStreamIdx; 
    AVCodecContext *pCodecCtx; 
    AVCodec      *pCodec; 
    AVFrame      *pFrame; 
    AVFrame      *pFrameRGB; 
    AVPacket      packet; 
    int          frameFinished; 
    int          numBytes; 
    uint8_t       *buffer; 
    static struct SwsContext *img_convert_ctx; 

    if(argc < 2){ 
     printf("Inserisci un file video\n"); 
     return -1; 
    } 

    //Registra tutti i formati e i codec 
    av_register_all(); 

    //Apre il file video 
    if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) != 0) 
    {return -1;} //Impossibile aprire il file 

    //Recupera le informazioni dello stream 
    if(avformat_find_stream_info(pFormatCtx, NULL) < 0) 
    {return -1;} // Couldn't find stream information 

    //Versa le informazioni del file sullo standard error 
    av_dump_format(pFormatCtx, 0, argv[1], 0); 

    //Trova il primo stream video 
    videoStreamIdx=-1; 
    for(i=0; i<pFormatCtx->nb_streams; i++) 
    { 
     if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
     { videoStreamIdx=i; 
      break;} 
    } 

    if(videoStreamIdx==-1) 
     return -1; // Impossibile trovare lo stream video 

    // Punta al contenuto del codec per lo stream video 
    pCodecCtx = pFormatCtx->streams[videoStreamIdx]->codec; 

    // Trova il decoder per lo stream video 
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id); 
    if(pCodec==NULL) 
    { 
     fprintf(stderr, "Codec Non Supportato!\n"); 
     return -1; //Impossibile trovare il codec 
    } 

    //Apre il codec 
    if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0) 
    {return -1;} //Impossibile aprire il codec 

    //Alloca il frame video 
    pFrame = av_frame_alloc(); 

    //Alloca una struct AVFrame 
    pFrameRGB = av_frame_alloc(); 
    if(pFrameRGB==NULL) 
    {return -1;} 

    //Determina la grandezza necessaria per il buffer e lo alloca 
    numBytes = avpicture_get_size(PIX_FMT_RGB24, 
                      pCodecCtx->width, 
                      pCodecCtx->height); 

    buffer = (uint8_t *) av_malloc(numBytes*sizeof(uint8_t)); 

    //Assegna le parti appropriate del buffer sulla superficie dell'immagine in pFrameRGB 
    //Tenere presente che pFrameRGB è un AVFrame, ma AVFrame è una superset di AVPicture 
    avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height); 

    int w = pCodecCtx->width; 
    int h = pCodecCtx->height; 
    img_convert_ctx = sws_getContext(w, h, pCodecCtx->pix_fmt, 
                         w, h, PIX_FMT_RGB24, 
                         SWS_LANCZOS, NULL, NULL, NULL); 

    //Legge i frame e salva i primi 5 frame su disco 
    i=0; 
    while((av_read_frame(pFormatCtx, &packet)>=0) && (i<5)) 
    { 
     //Questo è il packet dello stream video? 
     if(packet.stream_index==videoStreamIdx) 
     { 
      //Decodifica il frame video 
      avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); 

      //Si è riusiciti ad ottenere il frame video? 
      if(frameFinished) 
      { 
       i++; 
       sws_scale(img_convert_ctx, (const uint8_t * const *)pFrame->data, 
             pFrame->linesize, 0, pCodecCtx->height, 
             pFrameRGB->data, pFrameRGB->linesize); 
       SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i); 
      } 
     } 

     //Libera il pacchetto che era allocato da av_read_frame 
     av_free_packet(&packet); 
    } 

    //Libera l'immagine RGB 
    av_free(buffer); 
    av_free(pFrameRGB); 

    //Libera il frame YUV 
    av_free(pFrame); 

    //Chiude il codec 
    avcodec_close(pCodecCtx); 

    //Chiude il file video 
    avformat_close_input(&pFormatCtx); 

    /*FINE PROGRAMMA*/ 

    return 0; 
} 

Bu yapı çıkışı:

"/usr/bin/make" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf 
make[1]: ingresso nella directory "/home/dontrythisathome/Programmazione/C-C++/SimpleMediaPlayerForAndroid" 
"/usr/bin/make" -f nbproject/Makefile-Debug.mk dist/Debug/GNU-Linux-x86/simplemediaplayerforandroid 
make[2]: ingresso nella directory "/home/dontrythisathome/Programmazione/C-C++/SimpleMediaPlayerForAndroid" 
mkdir -p dist/Debug/GNU-Linux-x86 
gcc  -o dist/Debug/GNU-Linux-x86/simplemediaplayerforandroid build/Debug/GNU-Linux-x86/main.o -L/usr/lib/x86_64-linux-gnu -lavformat -lavcodec -lavutil -lswscale -lz -lbz2 
build/Debug/GNU-Linux-x86/main.o: In function `main': 
/home/dontrythisathome/Programmazione/C-C++/SimpleMediaPlayerForAndroid/main.c:105: undefined reference to `av_frame_alloc' 
/home/dontrythisathome/Programmazione/C-C++/SimpleMediaPlayerForAndroid/main.c:108: undefined reference to `av_frame_alloc' 
collect2: ld returned 1 exit status 
make[2]: *** [dist/Debug/GNU-Linux-x86/simplemediaplayerforandroid] Errore 1 
make[2]: uscita dalla directory "/home/dontrythisathome/Programmazione/C-C++/SimpleMediaPlayerForAndroid" 
make[1]: *** [.build-conf] Errore 2 
make[1]: uscita dalla directory "/home/dontrythisathome/Programmazione/C-C++/SimpleMediaPlayerForAndroid" 
make: *** [.build-impl] Errore 2 

BUILD FAILED (exit value 2, total time: 143ms) 

Ben de doğru kütüphane yolunu bağlantılı ve hiçbir hata bununla olmadığından yolunu başlıklarını

Bu benim programıdır. gcc -o prog1 /home/dontrythisathome/Programmazione/C-C++/SimpleMediaPlayerForAndroid/main.c -lavformat -lavcodec -lavutil -lswscale -lz -lbz2

Ve çıkış farklıdır: i bu komutları ile terminalden program oluşturmaya çalıştığınızda

Ama

/home/dontrythisathome/Programmazione/C-C++/SimpleMediaPlayerForAndroid/main.c:11:29: fatal error: libavutil/frame.h: File o directory non esistente 
compilation terminated. 

çıktı varolan hiçbir dosya veya dizin olduğunu söylüyor. Sorun nedir?

+0

Hangi ffmpeg sürümünü kullanıyorsunuz? Ubuntu deposundan mı yoksa kendiniz mi inşa ediyorsunuz? Bu API, yakın zamanda yayınlanan bir sürümde ekledi, yani belki de ffmpeg'iniz eskiydi. –

+0

Kendimi çözdüm ama bahşiş için teşekkürler. Benim ffmpeg kitaplık deponun eski ve ben inşa ettim ffmpeg offcial kaynak kodu deposundan güncel kütüphaneleri kullandım. – dontrythisathome

cevap

8

av_frame_alloc()lavc 55.28.1 eklendi ve böylece her iki yerine avcodec_alloc_frame() kullanabilir veya geleceğe uyumlu olmasını böyle bir şey yapmak: Jan Simek cevabı olduğu gibi

#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) 
    //Alloca il frame video 
    pFrame = av_frame_alloc(); 

    //Alloca una struct AVFrame 
    pFrameRGB = av_frame_alloc(); 
#else 
    pFrame = avcodec_alloc_frame(); 
    pFrameRGB = avcodec_alloc_frame(); 
#endif 
12

, biraz daha basit:

#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1) 
#define av_frame_alloc avcodec_alloc_frame 
#endif 
+2

Evet, bu daha iyi. Ve #define av_frame_free avcodec_free_frame' – user