FFmpeg:对av_frame_alloc()的未定义引用

时间:2014-06-05 10:05:57

标签: c ubuntu compilation ffmpeg

我想进入FFmpeg开发,我开始关注这些示例教程:here

我从第一个教程开始 - tutorial01.c - 但我遇到了这个'未定义的对av_frame_alloc()'的引用。

我在使用Ubuntu 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;
}

这是构建输出:

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

我还链接了正确的库路径和标头路径,因为没有错误。

但是当我尝试使用以下命令从终端构建程序时: gcc -o prog1 /home/dontrythisathome/Programmazione/C-C++/SimpleMediaPlayerForAndroid/main.c -lavformat -lavcodec -lavutil -lswscale -lz -lbz2

输出结果不同:

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

输出显示没有文件或目录存在。 有什么问题?

2 个答案:

答案 0 :(得分:16)

与Jan Simek的回答一样,更简单一点:

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

答案 1 :(得分:10)

lavc 55.28.1中添加了

av_frame_alloc(),因此您可以使用avcodec_alloc_frame()代替,也可以将来做以下事情:

#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