【问题标题】:error: undefined reference to 'av_free_packet(AVPacket*)' when use NDK to compile ffmpeg错误:使用 NDK 编译 ffmpeg 时未定义对 'av_free_packet(AVPacket*)' 的引用
【发布时间】:2013-07-22 06:10:55
【问题描述】:

我编译了我的 cpps 以通过我的 android MK 将 ffmpeg 库与 ANDROID NDK 一起使用,如下所示:

    LOCAL_PATH := $(call my-dir)
    DEFINES += -DTARGET_POSIX \
               -DTARGET_LINUX \
           -D_LINUX \
           -DTARGET_ANDROID \
           -D__STDC_CONSTANT_MACROS 

    include $(CLEAR_VARS)  
    LOCAL_MODULE := libavcodec
    LOCAL_SRC_FILES := lib/lib/libavcodec.so 
    include $(PREBUILT_SHARED_LIBRARY)  

    include $(CLEAR_VARS)  
    LOCAL_MODULE := libavfilter  
    LOCAL_SRC_FILES := lib/lib/libavfilter.so 
    include $(PREBUILT_SHARED_LIBRARY)  

    include $(CLEAR_VARS)  
    LOCAL_MODULE := libavformat  
    LOCAL_SRC_FILES := lib/lib/libavformat.so  
    include $(PREBUILT_SHARED_LIBRARY)  

    include $(CLEAR_VARS)  
    LOCAL_MODULE := libavutil  
    LOCAL_SRC_FILES := lib/lib/libavutil.so  
    include $(PREBUILT_SHARED_LIBRARY)  

    include $(CLEAR_VARS)  
    LOCAL_MODULE := libpostproc  
    LOCAL_SRC_FILES := lib/lib/libpostproc.so   
    include $(PREBUILT_SHARED_LIBRARY)  

    include $(CLEAR_VARS)  
    LOCAL_MODULE := libswresample  
    LOCAL_SRC_FILES := lib/lib/libswresample.so   
    include $(PREBUILT_SHARED_LIBRARY)  

    include $(CLEAR_VARS)  
    LOCAL_MODULE := libswscale  
    LOCAL_SRC_FILES := lib/lib/libswscale.so
    include $(PREBUILT_SHARED_LIBRARY)  

    include $(CLEAR_VARS)
    LOCAL_MODULE:= player
    base := $(LOCAL_PATH)
    LOCAL_SRC_FILES += cores/PlayDemux.cpp \
                   cores/PlayDemuxFFmpeg.cpp \
                   cores/PlayFactoryDemuxer.cpp

    LOCAL_C_INCLUDES += $(LOCAL_PATH) \
            $(LOCAL_PATH)/lib \
            $(LOCAL_PATH)/lib/include \
            $(LOCAL_PATH)/cores/player \
    LOCAL_CPPFLAGS += -Wall -fexceptions $(DEFINES)
    include $(BUILD_STATIC_LIBRARY)

    include $(CLEAR_VARS)
    LOCAL_MODULE:= testmain

    LOCAL_SRC_FILES := \
        testmain.cpp \

    LOCAL_C_INCLUDES += $(LOCAL_PATH) \
                $(LOCAL_PATH)/lib 
    LOCAL_CPPFLAGS += -Wall -fexceptions $(DEFINES)

    LOCAL_SHARED_LIBRARIES := libavcodec \
                libavformat \
                libavfilter \
                libavutil \
                libpostproc \
                libswscale \
                libswresample 

    LOCAL_STATIC_LIBRARIES := player 

    include $(BUILD_EXECUTABLE)

但是当我做“ndk-build v=1”时,编译后,我得到了:

    Install        : libavcodec.so => libs/armeabi-v7a/libavcodec.so
    install -p /cygdrive/d/player/obj/local/armeabi-v7a/libavcodec.so /cygdrive/d/player/libs/armeabi-v7a/libavcodec.so
    /cygdrive/d/android/android-ndk-r8e/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/arm-linux-androideabi-strip --strip-unneeded D:/player/libs/armeabi-v7a/libavcodec.so
    Install        : libavfilter.so => libs/armeabi-v7a/libavfilter.so
    install -p /cygdrive/d/player/obj/local/armeabi-v7a/libavfilter.so /cygdrive/d/player/libs/armeabi-v7a/libavfilter.so
    /cygdrive/d/android/android-ndk-r8e/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/arm-linux-androideabi-strip --strip-unneeded D:/player/libs/armeabi-v7a/libavfilter.so
    Install        : libavformat.so => libs/armeabi-v7a/libavformat.so
    install -p /cygdrive/d/player/obj/local/armeabi-v7a/libavformat.so /cygdrive/d/player/libs/armeabi-v7a/libavformat.so
    /cygdrive/d/android/android-ndk-r8e/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/arm-linux-androideabi-strip --strip-unneeded D:/player/libs/armeabi-v7a/libavformat.so
    Install        : libavutil.so => libs/armeabi-v7a/libavutil.so
    install -p /cygdrive/d/player/obj/local/armeabi-v7a/libavutil.so /cygdrive/d/player/libs/armeabi-v7a/libavutil.so
    /cygdrive/d/android/android-ndk-r8e/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/arm-linux-androideabi-strip --strip-unneeded D:/player/libs/armeabi-v7a/libavutil.so
    Install        : libpostproc.so => libs/armeabi-v7a/libpostproc.so
    install -p /cygdrive/d/player/obj/local/armeabi-v7a/libpostproc.so /cygdrive/d/player/libs/armeabi-v7a/libpostproc.so
    /cygdrive/d/android/android-ndk-r8e/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/arm-linux-androideabi-strip --strip-unneeded D:/player/libs/armeabi-v7a/libpostproc.so
    Install        : libswresample.so => libs/armeabi-v7a/libswresample.so
    install -p /cygdrive/d/player/obj/local/armeabi-v7a/libswresample.so /cygdrive/d/player/libs/armeabi-v7a/libswresample.so
    /cygdrive/d/android/android-ndk-r8e/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/arm-linux-androideabi-strip --strip-unneeded D:/player/libs/armeabi-v7a/libswresample.so
    Install        : libswscale.so => libs/armeabi-v7a/libswscale.so
    install -p /cygdrive/d/player/obj/local/armeabi-v7a/libswscale.so /cygdrive/d/player/libs/armeabi-v7a/libswscale.so
    /cygdrive/d/android/android-ndk-r8e/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/arm-linux-androideabi-strip --strip-unneeded D:/player/libs/armeabi-v7a/libswscale.so
    Executable     : testmain
    /cygdrive/d/android/android-ndk-r8e/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/arm-linux-androideabi-g++  -Wl,--gc-sections  -Wl,-z,nocopyreloc  --sysroot=D:/android/android-ndk-r8e/platforms/android-14/arch-arm  D:/player/obj/local/armeabi-v7a/objs/testmain/testmain.o D:/player/obj/local/armeabi-v7a/libplayer.a D:/android/android-ndk-r8e/sources/cxx-stl/stlport/libs/armeabi-v7a/libstlport_static.a -lgcc D:/player/obj/local/armeabi-v7a/libavcodec.so D:/player/obj/local/armeabi-v7a/libavformat.so D:/player/obj/local/armeabi-v7a/libavfilter.so D:/player/obj/local/armeabi-v7a/libavutil.so D:/player/obj/local/armeabi-v7a/libpostproc.so D:/player/obj/local/armeabi-v7a/libswscale.so D:/player/obj/local/armeabi-v7a/libswresample.so  -no-canonical-prefixes -march=armv7-a  -Wl,--fix-cortex-a8  -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now    -lc -lm  -o D:/player/obj/local/armeabi-v7a/testmain
    D:/android/android-ndk-r8e/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: D:/player/obj/local/armeabi-v7a/libplayer.a(PlayDemuxFFmpeg.o): in function PlayDemuxFFmpeg::Flush():D:/player/jni/lib/DllAvCodec.h:144: error: undefined reference to 'av_free_packet(AVPacket*)'

我使用的是 windows 7 + cygwin + NDKR8,但是编译了 ffmpeg 的 lib "libavcodec.so ,libavfilter.so,libavformat.so,libavutil.so,libpostproc.so,libswresample.so,libswscale.so"使用“ubuntu + NDK8”独立运行NDK。 我在头文件中包含外部“c”代码。

那么,如何纠正错误?

我的 DLLavcodec.h 是:

#pragma once
#include "DllAvUtil.h"

extern "C" {
  #include <libavcodec/avcodec.h>
}


class DllAvCodec : public DllAvCodecInterface
{
public:
  static CCriticalSection m_critSection;

  virtual ~DllAvCodec() {}
  virtual void avcodec_register_all()
  {
    ::avcodec_register_all();
  }
  virtual void avcodec_flush_buffers(AVCodecContext *avctx) { ::avcodec_flush_buffers(avctx); }
  virtual int avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options)
  {
    return ::avcodec_open2(avctx, codec, options);
  }
  virtual int avcodec_open2_dont_call(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options) { *(volatile int *)0x0 = 0; return 0; }
  virtual int avcodec_close_dont_call(AVCodecContext *avctx) { *(volatile int *)0x0 = 0; return 0; }
  virtual AVCodec *avcodec_find_decoder(enum CodecID id) { return ::avcodec_find_decoder(id); }
  virtual AVCodec *avcodec_find_encoder(enum CodecID id) { return ::avcodec_find_encoder(id); }
  virtual int avcodec_close(AVCodecContext *avctx)
  {
    return ::avcodec_close(avctx);
  }
  virtual AVFrame *avcodec_alloc_frame() { return ::avcodec_alloc_frame(); }
  virtual int avpicture_fill(AVPicture *picture, uint8_t *ptr, PixelFormat pix_fmt, int width, int height) { return ::avpicture_fill(picture, ptr, pix_fmt, width, height); }
  virtual int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, AVPacket *avpkt) { return ::avcodec_decode_video2(avctx, picture, got_picture_ptr, avpkt); }
  virtual int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { return ::avcodec_decode_audio4(avctx, frame, got_frame_ptr, avpkt); }
  virtual int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, AVPacket *avpkt) { return ::avcodec_decode_subtitle2(avctx, sub, got_sub_ptr, avpkt); }
  virtual int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, const short *samples) { return ::avcodec_encode_audio(avctx, buf, buf_size, samples); }
  virtual int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { return ::avcodec_encode_audio2(avctx, avpkt, frame, got_packet_ptr); }
  virtual int avpicture_get_size(PixelFormat pix_fmt, int width, int height) { return ::avpicture_get_size(pix_fmt, width, height); }
  virtual AVCodecContext *avcodec_alloc_context3(AVCodec *codec) { return ::avcodec_alloc_context3(codec); }
  virtual void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) { ::avcodec_string(buf, buf_size, enc, encode); }
  virtual void avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec) { ::avcodec_get_context_defaults3(s, codec); }

  virtual AVCodecParserContext *av_parser_init(int codec_id) { return ::av_parser_init(codec_id); }
  virtual int av_parser_parse2(AVCodecParserContext *s,AVCodecContext *avctx, uint8_t **poutbuf, int *poutbuf_size,
                    const uint8_t *buf, int buf_size,
                    int64_t pts, int64_t dts, int64_t pos)
  {
    return ::av_parser_parse2(s, avctx, poutbuf, poutbuf_size, buf, buf_size, pts, dts, pos);
  }
  virtual void av_parser_close(AVCodecParserContext *s) { ::av_parser_close(s); }

  virtual AVBitStreamFilterContext *av_bitstream_filter_init(const char *name) { return ::av_bitstream_filter_init(name); }
  virtual int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
    AVCodecContext *avctx, const char *args,
    uint8_t **poutbuf, int *poutbuf_size,
    const uint8_t *buf, int buf_size, int keyframe) { return ::av_bitstream_filter_filter(bsfc, avctx, args, poutbuf, poutbuf_size, buf, buf_size, keyframe); }
  virtual void av_bitstream_filter_close(AVBitStreamFilterContext *bsfc) { ::av_bitstream_filter_close(bsfc); }

  virtual void avpicture_free(AVPicture *picture) { ::avpicture_free(picture); }
  virtual void av_free_packet(AVPacket *pkt) { ::av_free_packet(pkt); }
  virtual int avpicture_alloc(AVPicture *picture, PixelFormat pix_fmt, int width, int height) { return ::avpicture_alloc(picture, pix_fmt, width, height); }
  virtual int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic) { return ::avcodec_default_get_buffer(s, pic); }
  virtual void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic) { ::avcodec_default_release_buffer(s, pic); }
  virtual enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat *fmt) { return ::avcodec_default_get_format(s, fmt); }
  virtual AVCodec *av_codec_next(AVCodec *c) { return ::av_codec_next(c); }

  virtual int av_dup_packet(AVPacket *pkt) { return ::av_dup_packet(pkt); }
  virtual void av_init_packet(AVPacket *pkt) { return ::av_init_packet(pkt); }
  virtual int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, enum AVSampleFormat sample_fmt, const uint8_t *buf, int buf_size, int align) { return ::avcodec_fill_audio_frame(frame, nb_channels, sample_fmt, buf, buf_size, align); }
  virtual void avcodec_free_frame(AVFrame **frame) { return ::avcodec_free_frame(frame); };
};

【问题讨论】:

  • 请发布DllAvCodec.h 文件。恐怕还是少了一些extern "C"
  • 好的,DllAvCodec.h 已发布

标签: android c++ android-ndk ffmpeg linker-errors


【解决方案1】:

我做了一个小实验。我相信问题仍然在于extern "C"。您发布了 DllAvCodec.h 文件,但恐怕您在 PlayDemuxFFmpeg.cpp#include 没有 extern "C" 包装器的 ffmpeg 标头(可能不在 cpp 文件,但在 DllAvCodec.h 之前包含的标头之一中。

【讨论】:

  • 是的!我在 DllAvCodec.h 之前找到了一个没有 extern "C" 的包含标头,谢谢!!!
  • @Alex Cohn 你能看到这个问题吗?从上周开始我真的很挣扎:stackoverflow.com/questions/36745535/…
【解决方案2】:

请尝试重新洗牌:

LOCAL_SHARED_LIBRARIES := \
            libavformat \
            libavcodec \
            libavfilter \
            libavutil \
            libpostproc \
            libswscale \
            libswresample

【讨论】:

  • 我重新编译了 ffmpeg 库,但仍然报错:未定义引用 'av_free_packet(AVPacket*)'
  • 但我转储了那个符号:arm-linux-androideabi-nm lib/lib/libavcodec.a | grep av_free_packet 00000770 T av_free_packet U av_free_packet
  • 你重新编译了什么
  • 我重新编译了ffmpeg1.2 lib,并与命令链接,但仍然出现错误
【解决方案3】:

这是因为 avcodec.h 文件中缺少方法 av_free_packet(AVPacket *)。 请确认它是否存在。

【讨论】:

  • 不,“未定义引用”表示方法(其实是函数,因为ffmpeg是C写的,没有C++对象/方法)被声明,编译器发现它在头文件中,但链接器在库中找不到它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-23
  • 1970-01-01
  • 2019-05-29
  • 2017-11-27
  • 1970-01-01
  • 2016-12-09
  • 1970-01-01
相关资源
最近更新 更多