本文转载至: http://witmax.cn/ffmpeg-img-convert.html
FFmpeg编译出错undefined reference to `img_convert’的解决方法
刚准备拿FFmpeg做点东西,在Ubuntu上安装了最新的FFmpeg v0.6.1,找了一段实例程序(见文末)来编译,结果出现了一下编译错误:
1
2
3
4
|
test.c:212: warning: implicit declaration of function 'img_convert'
/tmp/cc3q7gsX.o: In function `main':
test.c:(.text+0xbf0): undefined reference to `img_convert'
collect2: ld returned 1 exit status
|
这段程序以前在FFmpeg v0.4.9版本上是可以编译的,无奈在Ubuntu上装不上v0.4.9版,只好根据CSDN论坛版友的提示来修改一下程序。
问题出现在我下载的ffmpeg的版本不一样,我是用svn下载了最新的版本,在这个版本的函数库里没有img_convert函数,在0.4.8以前的版本中还有这个函数,新版本中用sws_getContext和sws_scale代替了。简单说明如下:
新版本的ffmpeg添加了新的接口:libswscale来处理图像缩放。
以前使用img_convert来把RGB转换成YUV12,现在使用新的接口。新接口更加标准和快速,而且里面有了MMX优化代码。换句话说,它是做缩放更好的方式。
用来缩放的基本函数是sws_scale。但一开始,必需建立一个SwsContext的概念。这将进行想要的转换,然后把它传递给 sws_scale函数。类似于在SQL中的预备阶段或者是在Python中编译的规则表达式regexp。要准备这个上下文,使用 sws_getContext函数,它需要源的宽度和高度,我们想要的宽度和高度,源的格式和想要转换成的格式,同时还有一些其它的参数和标志。然后我们像使用img_convert一样来使用sws_scale函数,唯一不同的是我们传递给的是SwsContext。
解决办法是将原有的img_convert函数改为sws_scale函数,原来的函数调用为:
1
2
3
4
|
// Convert the image from its native format to RGB
img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24,
(AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width,
pCodecCtx->height);
|
修改为
01
02
03
04
05
06
07
08
09
10
11
|
#include <ffmpeg/swscale.h>
// other codes
static
struct
SwsContext *img_convert_ctx;
// other codes
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
// other codes
// Convert the image from its native format to RGB
sws_scale(img_convert_ctx, (
const
uint8_t*
const
*)pFrame->data, pFrame->linesize,
0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
|
编译正常,测试后程序可用,搞定。
以下为原来的测试程序源码:
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
// tutorial01.c
// Code based on a tutorial by Martin Bohme (<a href="mailto:boehme@inb.uni-luebeckREMOVETHIS.de">boehme@inb.uni-luebeckREMOVETHIS.de</a>)
// Tested on Gentoo, CVS version 5/01/07 compiled with GCC 4.1.1
// A small sample program that shows how to use libavformat and libavcodec to
// read video from a file.
//
// Use
//
// gcc -o tutorial01 tutorial01.c -lavformat -lavcodec -lz
//
// to build (assuming libavformat and libavcodec are correctly installed
// your system).
//
// Run using
//
// tutorial01 myvideofile.mpg
//
// to write the first five frames from "myvideofile.mpg" to disk in PPM
// format.
#include <ffmpeg/avcodec.h>
#include <ffmpeg/avformat.h>
#include <stdio.h>
void
SaveFrame(AVFrame *pFrame,
int
width,
int
height,
int
iFrame) {
FILE
*pFile;
char
szFilename[32];
int
y;
// Open file
sprintf
(szFilename,
"frame%d.ppm"
, iFrame);
pFile=
fopen
(szFilename,
"wb"
);
if
(pFile==NULL)
return
;
// Write header
fprintf
(pFile,
"P6\n%d %d\n255\n"
, width, height);
// Write pixel data
for
(y=0; y<height; y++)
fwrite
(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
// Close file
fclose
(pFile);
}
int
main(
int
argc,
char
*argv[]) {
AVFormatContext *pFormatCtx;
int
i, videoStream;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame;
AVFrame *pFrameRGB;
AVPacket packet;
int
frameFinished;
int
numBytes;
uint8_t *buffer;
if
(argc < 2) {
printf
(
"Please provide a movie file\n"
);
return
-1;
}
// Register all formats and codecs
av_register_all();
// Open video file
if
(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
return
-1;
// Couldn't open file
// Retrieve stream information
if
(av_find_stream_info(pFormatCtx)<0)
return
-1;
// Couldn't find stream information
// Dump information about file onto standard error
dump_format(pFormatCtx, 0, argv[1], 0);
// Find the first video stream
videoStream=-1;
for
(i=0; i<pFormatCtx->nb_streams; i++)
if
(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {
videoStream=i;
break
;
}
if
(videoStream==-1)
return
-1;
// Didn't find a video stream
// Get a pointer to the codec context for the video stream
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
// Find the decoder for the video stream
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if
(pCodec==NULL) {
fprintf
(stderr,
"Unsupported codec!\n"
);
return
-1;
// Codec not found
}
// Open codec
if
(avcodec_open(pCodecCtx, pCodec)<0)
return
-1;
// Could not open codec
// Allocate video frame
pFrame=avcodec_alloc_frame();
// Allocate an AVFrame structure
pFrameRGB=avcodec_alloc_frame();
if
(pFrameRGB==NULL)
return
-1;
// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
pCodecCtx->height);
buffer=(uint8_t *)av_malloc(numBytes*
sizeof
(uint8_t));
// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
pCodecCtx->width, pCodecCtx->height);
// Read frames and save first five frames to disk
i=0;
while
(av_read_frame(pFormatCtx, &packet)>=0) {
// Is this a packet from the video stream?
if
(packet.stream_index==videoStream) {
// Decode video frame
avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
packet.data, packet.size);
// Did we get a video frame?
if
(frameFinished) {
// Convert the image from its native format to RGB
img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24,
(AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width,
pCodecCtx->height);
// Save the frame to disk
if
(++i<=5)
SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height,
i);
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
// Free the RGB image
av_free(buffer);
av_free(pFrameRGB);
// Free the YUV frame
av_free(pFrame);
// Close the codec
avcodec_close(pCodecCtx);
// Close the video file
av_close_input_file(pFormatCtx);
return
0;
}
|