2014-06-05 13 views
8

Tôi muốn nhận được vào FFmpeg phát triển và tôi bắt đầu làm theo các mẫu hướng dẫn ở đây: hereFFmpeg: tài liệu tham khảo không xác định để av_frame_alloc()

tôi bắt đầu với hướng dẫn đầu tiên - tutorial01.c - nhưng tôi chạy vào vấn đề này ' tham chiếu không xác định đối với av_frame_alloc() '.

Tôi đang sử dụng Ubuntu 12.04 LTS.

Đây là chương trình của tôi:

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

Đây là build đầu ra:

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

tôi cũng liên kết các đường dẫn thư viện chính xác và tiêu đề con đường vì không có lỗi với điều đó.

Nhưng khi tôi cố gắng để xây dựng các chương trình từ thiết bị đầu cuối với các lệnh: gcc -o prog1 /home/dontrythisathome/Programmazione/C-C++/SimpleMediaPlayerForAndroid/main.c -lavformat -lavcodec -lavutil -lswscale -lz -lbz2

Và đầu ra là khác nhau:

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

Sản lượng nói rằng không có tập tin hoặc thư mục hiện có. Vấn đề là gì?

+0

Bạn sử dụng phiên bản ffmpeg nào? Là nó từ kho lưu trữ Ubuntu hoặc bạn xây dựng nó một mình? API này được thêm vào trong bản phát hành gần đây, vì vậy có thể ffmpeg của bạn đã lỗi thời. –

+0

Tôi tự giải quyết nhưng cảm ơn cho tip. Kho lưu trữ thư viện ffmpeg của tôi đã lỗi thời và tôi đã sử dụng các thư viện được cập nhật từ kho mã nguồn ffmpeg offcial tôi đã xây dựng. – dontrythisathome

Trả lời

8

av_frame_alloc() đã được bổ sung trong lavc 55.28.1, vì vậy bạn có thể thể sử dụng avcodec_alloc_frame() thay vì hoặc là bằng chứng trong tương lai làm một cái gì đó như thế này:

#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

Như với câu trả lời Jan Simek, một chút đơn giản hơn:

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

Vâng, điều này tốt hơn. Và '#define av_frame_free avcodec_free_frame' – user

Các vấn đề liên quan