2014-06-05 15 views
8

Voglio entrare in FFmpeg via di sviluppo e ho iniziato a seguire questi esempi tutorial qui: hereFFmpeg: riferimenti non definiti per av_frame_alloc()

Ho iniziato con il primo tutorial - tutorial01.c - ma mi imbatto in questo problema ' riferimenti indefiniti a av_frame_alloc() '.

Sono su Ubuntu 12.04 LTS.

Questo è il mio programma:

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

Questa è l'uscita di costruzione:

"/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) 

ho anche legato il percorso libreria corretta e intestazioni percorso perché non v'è alcun errore con questo.

ma quando provo a costruire il programma dal terminale con questi comandi: gcc -o prog1 /home/dontrythisathome/Programmazione/C-C++/SimpleMediaPlayerForAndroid/main.c -lavformat -lavcodec -lavutil -lswscale -lz -lbz2

e l'uscita è diverso:

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

L'output afferma che non v'è alcun file o directory esistente. Qual è il problema?

+0

Quale versione di ffmpeg usi? Proviene dal repository di Ubuntu o lo costruisci da solo? Questa API è stata aggiunta in una versione recente, quindi forse il tuo ffmpeg non è aggiornato. –

+0

Mi sono risolto ma grazie per il suggerimento. Il mio repository della libreria ffmpeg era obsoleto e ho usato librerie aggiornate dal repository di codice sorgente ffmpeg che ho creato. – dontrythisathome

risposta

8

av_frame_alloc() è stato aggiunto in lavc 55.28.1, così da poter utilizzare sia avcodec_alloc_frame() invece o per essere a prova di futuro fare qualcosa di simile:

#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

Come con la risposta di Jan Simek, un po 'più semplice:

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

Sì, è meglio. E '#define av_frame_free avcodec_free_frame' – user

Problemi correlati