免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 9957 | 回复: 10
打印 上一主题 下一主题

[C++] 奇怪的编译器连接错误,十万火急!!! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-17 10:50 |只看该作者 |倒序浏览
遇到奇怪的编译器连接问题,希望各位大虾能帮小弟解决:

我下载编译了ffmpeg解码库,里面包含了libavcodec、libavformat等库,并且安装在默认库搜索目录/usr/lib中。然后我用g++编译一个例子程序avcodec_sample.cpp,命令为
g++ -o avcodec_sample avcodec_sample.cpp -lavformat -lavcodec -ldts -lz -lavutil
命令中所有库都已经在/usr/lib中,结果提示出现错误,例如
undefined reference to `av_free(void*)'
其中av_free(void*)是库文件中已经有的函数

然后我查过gcc的默认库搜索目录,得到结果是没有变化,我再把相关的库文件复制到/lib中,再次用上面的命令编译,得到相同结果

我再把-L参数加到命令中,命令变为
g++ -o avcodec_sample avcodec_sample.cpp -L /usr/lib  -lavformat -lavcodec -ldts -lz -lavutil
结果同样提示错误

最使我感到迷惑的是我将命令改成
g++ -o avcodec_sample avcodec_sample.cpp
在没有把库加上去的时候同样提示错误,并且出错信息是一样的!!!

以上所有尝试出错信息都一样,我真的不知道该怎么编译才好,希望有人能帮我解决这个问题

论坛徽章:
0
2 [报告]
发表于 2009-04-17 10:56 |只看该作者
源码?

论坛徽章:
0
3 [报告]
发表于 2009-04-17 11:00 |只看该作者
源码中加入extern "C"试试

extern "C"
{
#include "avformat.h"
#include "swscale.h"
}

论坛徽章:
0
4 [报告]
发表于 2009-04-17 11:03 |只看该作者
在ffmpeg所有的源码是用c写的,g++默认的编译语言是C++,它需要指定链接库的decoration, 如cdecl, stdcall(请参考google). 如果decoration没有指定,就会认为函数的实现部分在源码里面,于是就不会到链接库里面找。也许是这个原因

论坛徽章:
0
5 [报告]
发表于 2009-04-17 11:08 |只看该作者

回复 #3 nlylidb 的帖子

问题依旧

论坛徽章:
0
6 [报告]
发表于 2009-04-17 11:09 |只看该作者
原帖由 nlylidb 于 2009-4-17 10:56 发表
源码?

// avcodec_sample.cpp

// A small sample program that shows how to use libavformat and libavcodec to
// read video from a file.
//
// Use
//
// g++ -o avcodec_sample avcodec_sample.cpp -lavformat -lavcodec -lz
//
// to build (assuming libavformat and libavcodec are correctly installed on
// your system).
//
// Run using
//
// avcodec_sample myvideofile.mpg
//
// to write the first five frames from "myvideofile.mpg" to disk in PPM
// format.

extern "C"
{
#include <ffmpeg/avcodec.h>
#include <ffmpeg/avformat.h>
#include <ffmpeg/avutil.h>

#include <stdio.h>
}

bool GetNextFrame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx,
    int videoStream, AVFrame *pFrame)
{
    static AVPacket packet;
    static int      bytesRemaining=0;
    static uint8_t  *rawData;
    static bool     fFirstTime=true;
    int             bytesDecoded;
    int             frameFinished;

    // First time we're called, set packet.data to NULL to indicate it
    // doesn't have to be freed
    if(fFirstTime)
    {
        fFirstTime=false;
        packet.data=NULL;
    }

    // Decode packets until we have decoded a complete frame
    while(true)
    {
        // Work on the current packet until we have decoded all of it
        while(bytesRemaining > 0)
        {
            // Decode the next chunk of data
            bytesDecoded=avcodec_decode_video(pCodecCtx, pFrame,
                &frameFinished, rawData, bytesRemaining);

            // Was there an error?
            if(bytesDecoded < 0)
            {
                fprintf(stderr, "Error while decoding frame\n");
                return false;
            }

            bytesRemaining-=bytesDecoded;
            rawData+=bytesDecoded;

            // Did we finish the current frame? Then we can return
            if(frameFinished)
                return true;
        }

        // Read the next packet, skipping all packets that aren't for this
        // stream
        do
        {
            // Free old packet
            if(packet.data!=NULL)
                av_free_packet(&packet);

            // Read new packet
            if(av_read_packet(pFormatCtx, &packet)<0)
                goto loop_exit;
        } while(packet.stream_index!=videoStream);

        bytesRemaining=packet.size;
        rawData=packet.data;
    }

loop_exit:

    // Decode the rest of the last frame
    bytesDecoded=avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
        rawData, bytesRemaining);

    // Free last packet
    if(packet.data!=NULL)
        av_free_packet(&packet);

    return frameFinished!=0;
}

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;
    int             numBytes;
    uint8_t         *buffer;

    // 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], false);

    // Find the first video stream
    videoStream=-1;
    for(i=0; i<pFormatCtx->nb_streams; i++)
        if(pFormatCtx->streams->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)
        return -1; // Codec not found

    // Inform the codec that we can handle truncated bitstreams -- i.e.,
    // bitstreams where frame boundaries can fall in the middle of packets
    if(pCodec->capabilities & CODEC_CAP_TRUNCATED)
        pCodecCtx->flags|=CODEC_FLAG_TRUNCATED;

    // Open codec
    if(avcodec_open(pCodecCtx, pCodec)<0)
        return -1; // Could not open codec

    // Hack to correct wrong frame rates that seem to be generated by some
    // codecs
    //if(pCodecCtx->frame_rate>1000 && pCodecCtx->frame_rate_base==1)
    //  pCodecCtx->frame_rate_base=1000;

    // 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=new uint8_t[numBytes];

    // Assign appropriate parts of buffer to image planes in pFrameRGB
    avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
        pCodecCtx->width, pCodecCtx->height);

    // Read frames and save first five frames to disk
    i=0;
    while(GetNextFrame(pFormatCtx, pCodecCtx, videoStream, pFrame))
    {
        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 RGB image
    delete [] 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
7 [报告]
发表于 2009-04-17 11:34 |只看该作者
我的ffmpeg可能和你的版本有点不一样
           if(pFormatCtx->streams->codec->codec_type==CODEC_TYPE_VIDEO)
其中AVFormatContext中的streams是数组形式的,你这个直接报错,该成了
           if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)

再编译的时候现在只有一个错误和两个警告

ffmpeg.cpp: In function ‘int main(int, char**)’:
ffmpeg.cpp:204: 警告:不建议使用‘int img_convert(AVPicture*, int, const AVPicture*, int, int, int)’(声明于 /usr/include/ffmpeg/avcodec.h:2550)
ffmpeg.cpp:205: 警告:不建议使用‘int img_convert(AVPicture*, int, const AVPicture*, int, int, int)’(声明于 /usr/include/ffmpeg/avcodec.h:2550)
/tmp/ccAXlFR2.o: In function `main':
ffmpeg.cpp.text+0x487): undefined reference to `img_convert'
collect2: ld 返回 1

如果不加extern "C"的时候编译结果为:

ffmpeg.cpp: In function ‘int main(int, char**)’:
ffmpeg.cpp:204: 警告:不建议使用‘int img_convert(AVPicture*, int, const AVPicture*, int, int, int)’(声明于 /usr/include/ffmpeg/avcodec.h:2550)
ffmpeg.cpp:205: 警告:不建议使用‘int img_convert(AVPicture*, int, const AVPicture*, int, int, int)’(声明于 /usr/include/ffmpeg/avcodec.h:2550)
/tmp/ccNifaJe.o: In function `GetNextFrame(AVFormatContext*, AVCodecContext*, int, AVFrame*)':
ffmpeg.cpp.text+0x135): undefined reference to `avcodec_decode_video(AVCodecContext*, AVFrame*, int*, unsigned char const*, int)'
ffmpeg.cpp.text+0x1cd): undefined reference to `av_read_packet(AVFormatContext*, AVPacket*)'
ffmpeg.cpp.text+0x222): undefined reference to `avcodec_decode_video(AVCodecContext*, AVFrame*, int*, unsigned char const*, int)'
/tmp/ccNifaJe.o: In function `main':
ffmpeg.cpp.text+0x262): undefined reference to `av_register_all()'
ffmpeg.cpp.text+0x294): undefined reference to `av_open_input_file(AVFormatContext**, char const*, AVInputFormat*, int, AVFormatParameters*)'
ffmpeg.cpp.text+0x2b4): undefined reference to `av_find_stream_info(AVFormatContext*)'
ffmpeg.cpp.text+0x2f1): undefined reference to `dump_format(AVFormatContext*, int, char const*, int)'
ffmpeg.cpp.text+0x36a): undefined reference to `avcodec_find_decoder(CodecID)'
ffmpeg.cpp.text+0x3b2): undefined reference to `avcodec_open(AVCodecContext*, AVCodec*)'
ffmpeg.cpp:(.text+0x3ca): undefined reference to `avcodec_alloc_frame()'
ffmpeg.cpp:(.text+0x3d2): undefined reference to `avcodec_alloc_frame()'
ffmpeg.cpp:(.text+0x407): undefined reference to `avpicture_get_size(int, int, int)'
ffmpeg.cpp:(.text+0x446): undefined reference to `avpicture_fill(AVPicture*, unsigned char*, int, int, int)'
ffmpeg.cpp:(.text+0x487): undefined reference to `img_convert(AVPicture*, int, AVPicture const*, int, int, int)'
ffmpeg.cpp:(.text+0x500): undefined reference to `av_free(void*)'
ffmpeg.cpp:(.text+0x50b): undefined reference to `av_free(void*)'
ffmpeg.cpp:(.text+0x516): undefined reference to `avcodec_close(AVCodecContext*)'
ffmpeg.cpp:(.text+0x521): undefined reference to `av_close_input_file(AVFormatContext*)'
collect2: ld 返回 1


说明extern "C"还是有作用的,现在在看img_convert的问题

[ 本帖最后由 nlylidb 于 2009-4-17 11:35 编辑 ]

论坛徽章:
0
8 [报告]
发表于 2009-04-17 11:40 |只看该作者
你现在的错误是什么?能发出来么?
我发现在我的头文件中img_convert的定义是这样的:

#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8 )+0)
/**
* convert among pixel formats
* @deprecated Use the software scaler (swscale) instead.
*/
attribute_deprecated int img_convert(AVPicture *dst, int dst_pix_fmt,
                const AVPicture *src, int pix_fmt,
                int width, int height);
#endif

论坛徽章:
0
9 [报告]
发表于 2009-04-17 11:46 |只看该作者
原帖由 nlylidb 于 2009-4-17 11:34 发表
我的ffmpeg可能和你的版本有点不一样
           if(pFormatCtx->streams->codec->codec_type==CODEC_TYPE_VIDEO)
其中AVFormatContext中的streams是数组形式的,你这个直接报错,该成了
           if(pFo ...

能不能把您的cpp文件贴上来?

论坛徽章:
0
10 [报告]
发表于 2009-04-17 11:48 |只看该作者
// avcodec_sample.cpp

// A small sample program that shows how to use libavformat and libavcodec to
// read video from a file.
//
// Use
//
// g++ -o avcodec_sample avcodec_sample.cpp -lavformat -lavcodec -lz
//
// to build (assuming libavformat and libavcodec are correctly installed on
// your system).
//
// Run using
//
// avcodec_sample myvideofile.mpg
//
// to write the first five frames from "myvideofile.mpg" to disk in PPM
// format.

extern "C"
{
#include <ffmpeg/avcodec.h>
#include <ffmpeg/avformat.h>
#include <ffmpeg/avutil.h>

#include <stdio.h>
}

bool GetNextFrame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx,
    int videoStream, AVFrame *pFrame)
{
    static AVPacket packet;
    static int      bytesRemaining=0;
    static uint8_t  *rawData;
    static bool     fFirstTime=true;
    int             bytesDecoded;
    int             frameFinished;

    // First time we're called, set packet.data to NULL to indicate it
    // doesn't have to be freed
    if(fFirstTime)
    {
        fFirstTime=false;
        packet.data=NULL;
    }

    // Decode packets until we have decoded a complete frame
    while(true)
    {
        // Work on the current packet until we have decoded all of it
        while(bytesRemaining > 0)
        {
            // Decode the next chunk of data
            bytesDecoded=avcodec_decode_video(pCodecCtx, pFrame,
                &frameFinished, rawData, bytesRemaining);

            // Was there an error?
            if(bytesDecoded < 0)
            {
                fprintf(stderr, "Error while decoding frame\n");
                return false;
            }

            bytesRemaining-=bytesDecoded;
            rawData+=bytesDecoded;

            // Did we finish the current frame? Then we can return
            if(frameFinished)
                return true;
        }

        // Read the next packet, skipping all packets that aren't for this
        // stream
        do
        {
            // Free old packet
            if(packet.data!=NULL)
                av_free_packet(&packet);

            // Read new packet
            if(av_read_packet(pFormatCtx, &packet)<0)
                goto loop_exit;
        } while(packet.stream_index!=videoStream);

        bytesRemaining=packet.size;
        rawData=packet.data;
    }

loop_exit:

    // Decode the rest of the last frame
    bytesDecoded=avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
        rawData, bytesRemaining);

    // Free last packet
    if(packet.data!=NULL)
        av_free_packet(&packet);

    return frameFinished!=0;
}

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;
    int             numBytes;
    uint8_t         *buffer;

    // 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], false);

    // 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)
        return -1; // Codec not found

    // Inform the codec that we can handle truncated bitstreams -- i.e.,
    // bitstreams where frame boundaries can fall in the middle of packets
    if(pCodec->capabilities & CODEC_CAP_TRUNCATED)
        pCodecCtx->flags|=CODEC_FLAG_TRUNCATED;

    // Open codec
    if(avcodec_open(pCodecCtx, pCodec)<0)
        return -1; // Could not open codec

    // Hack to correct wrong frame rates that seem to be generated by some
    // codecs
    //if(pCodecCtx->frame_rate>1000 && pCodecCtx->frame_rate_base==1)
    //  pCodecCtx->frame_rate_base=1000;

    // 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=new uint8_t[numBytes];

    // Assign appropriate parts of buffer to image planes in pFrameRGB
    avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
        pCodecCtx->width, pCodecCtx->height);

    // Read frames and save first five frames to disk
    i=0;
    while(GetNextFrame(pFormatCtx, pCodecCtx, videoStream, pFrame))
    {
        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 RGB image
    delete [] 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;
}

一样的,难道是这个代码模式的问题?能把你编译的错误信息贴出来么

[ 本帖最后由 nlylidb 于 2009-4-17 11:56 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP