FFmpeg编译出错undefined reference to `img_convert’的解决方法

本文转载至: http://witmax.cn/ffmpeg-img-convert.html


FFmpeg编译出错undefined reference to `img_convert’的解决方法

2011年1月3日 发表评论 阅读评论

刚准备拿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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值