我想进入ffmpeg的开发,我开始在这里学习这些示例教程:here
我从第一个教程tutorial01.c开始,但是遇到了这个问题“对av_frame_alloc()的未定义引用”。
我在Ubuntu12.04LTS上。
这是我的程序:
/*
* 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.
输出表示没有文件或目录存在。
问题是什么?
最佳答案
正如简·西梅克的回答,简单一点:
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)
#define av_frame_alloc avcodec_alloc_frame
#endif