0

当我在 Cplusplus 包装器中使用 android NDK 调用 ffmpeg1.2.1 lib 时,某些符号无法链接,链接时出现以下错误。但是其他符号可以链接,为什么?如何纠正错误?

SharedLibrary  : libplayer.so
/home/mytest/player/jni/lib/DllAvCodec.h:124: error: undefined reference to 'avcodec_string(char*, int, AVCodecContext*, int)'
/home/mytest/player/jni/lib/DllAvCodec.h:124: error: undefined reference to 'avcodec_string(char*, int, AVCodecContext*, int)'
/home/mytest/player/jni/lib/DllAvCodec.h:124: error: undefined reference to 'avcodec_string(char*, int, AVCodecContext*, int)'
/home/mytest/player/jni/lib/DllAvCodec.h:144: error: undefined reference to 'av_free_packet(AVPacket*)'
/home/mytest/player/jni/cores/player/Demuxers/DemuxFFmpeg.cpp:248: error: undefined reference to 'av_log_set_callback(void (*)(void*,mytestt*,     std::__va_list))'
/home/mytest/player/jni/lib/DllAvCodec.h:144: error: undefined reference to 'av_free_packet(AVPacket*)'
/home/mytest/player/jni/cores/player/Demuxers/DemuxFFmpeg.cpp:701: error: undefined reference to 'av_free_packet(AVPacket*)'
/home/mytest/player/jni/cores/player/Demuxers/DemuxFFmpeg.cpp:798: error: undefined reference to 'av_free_packet(AVPacket*)'
/home/mytest/player/jni/lib/DllAvCodec.h:108: error: undefined reference to 'avcodec_find_decoder(AVCodecID)'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)    

我的 android.mk 是:

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

######################################
#build ffmpeg prebuilt lib
######################################
include $(CLEAR_VARS)  
LOCAL_MODULE := libavcodec
LOCAL_SRC_FILES :=lib/lib/libavcodec.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)  
LOCAL_MODULE := libavfilter  
LOCAL_SRC_FILES :=lib/lib/libavfilter.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)  
LOCAL_MODULE := libavformat  
LOCAL_SRC_FILES :=lib/lib/libavformat.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)  
LOCAL_MODULE := libavutil  
LOCAL_SRC_FILES :=lib/lib/libavutil.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)  
LOCAL_MODULE := libpostproc  
LOCAL_SRC_FILES :=lib/lib/libpostproc.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)  
LOCAL_MODULE := libswresample  
LOCAL_SRC_FILES :=lib/lib/libswresample.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)  
LOCAL_MODULE := libswscale  
LOCAL_SRC_FILES := lib/lib/libswscale.a
include $(PREBUILT_STATIC_LIBRARY)


######################################
#build lib
######################################
include $(CLEAR_VARS)
LOCAL_MODULE:= player
base := $(LOCAL_PATH)

LOCAL_SRC_FILES += ... #ignore


LOCAL_C_INCLUDES += $(LOCAL_PATH) \
            $(LOCAL_PATH)/lib \
            $(LOCAL_PATH)/lib/include \
            $(LOCAL_PATH)/cores/dvdplayer \

LOCAL_CPPFLAGS += -Wall -fexceptions $(DEFINES)

LOCAL_STATIC_LIBRARIES := libavformat libavcodec libavfilter  \
                          libavutil libpostproc libswscale libswresample 

LOCAL_LDLIBS += -llog -lz 
LOCAL_LDFLAGS += -L../jni/lib/lib  

include $(BUILD_SHARED_LIBRARY)

DllAvcodec.h 是:

#pragma once


#include "DllAvUtil.h"
#include "utils/log.h"
#define USE_EXTERNAL_FFMPEG  1

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

#if LIBAVCODEC_VERSION_MICRO >= 100
  #define LIBAVCODEC_FROM_FFMPEG
#else
  #define LIBAVCODEC_FROM_LIBAV
#endif

#include "threads/SingleLock.h"

class DllAvCodecInterface
{
public:
  virtual ~DllAvCodecInterface() {}
  virtual void avcodec_register_all(void)=0;
  virtual void avcodec_flush_buffers(AVCodecContext *avctx)=0;
  virtual int avcodec_open2_dont_call(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options)=0;
  virtual AVCodec *avcodec_find_decoder(enum CodecID id)=0;
  virtual AVCodec *avcodec_find_encoder(enum CodecID id)=0;
  virtual int avcodec_close_dont_call(AVCodecContext *avctx)=0;
  virtual AVFrame *avcodec_alloc_frame(void)=0;
  virtual int avpicture_fill(AVPicture *picture, uint8_t *ptr, PixelFormat pix_fmt, int width, int height)=0;
  virtual int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, AVPacket *avpkt)=0;
  virtual int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt)=0;
  virtual int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, AVPacket *avpkt)=0;
  ///virtual int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, const short *samples)=0;
  ///virtual int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr)=0;
  virtual int avpicture_get_size(PixelFormat pix_fmt, int width, int height)=0;
  virtual AVCodecContext *avcodec_alloc_context3(AVCodec *codec)=0;
  virtual void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)=0;
  virtual void avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec)=0;
  virtual AVCodecParserContext *av_parser_init(int codec_id)=0;
  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)=0;
  virtual void av_parser_close(AVCodecParserContext *s)=0;
  virtual AVBitStreamFilterContext *av_bitstream_filter_init(const char *name)=0;
  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) =0;
  virtual void av_bitstream_filter_close(AVBitStreamFilterContext *bsfc) =0;
  virtual void avpicture_free(AVPicture *picture)=0;
  virtual void av_free_packet(AVPacket *pkt)=0;
  virtual int avpicture_alloc(AVPicture *picture, PixelFormat pix_fmt, int width, int height)=0;
  virtual enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat *fmt)=0;
  virtual int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic)=0;
  virtual void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic)=0;
  virtual AVCodec *av_codec_next(AVCodec *c)=0;
  virtual int av_dup_packet(AVPacket *pkt)=0;
  virtual void av_init_packet(AVPacket *pkt)=0;
  virtual int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, enum AVSampleFormat sample_fmt, const uint8_t *buf, int buf_size, int align) = 0;
  virtual void avcodec_free_frame(AVFrame **frame)=0;
};


// Use direct layer
class DllAvCodec : public DllAvCodecInterface
{
public:
  static CCriticalSection m_critSection;

  virtual ~DllAvCodec() {}
  virtual void avcodec_register_all()
  {
    CSingleLock lock(DllAvCodec::m_critSection);
    ::avcodec_register_all();
  }
  virtual void avcodec_flush_buffers(AVCodecContext *avctx) { ::avcodec_flush_buffers(avctx); }
  virtual int avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options)
  {
    CSingleLock lock(DllAvCodec::m_critSection);
    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)
  {
    CSingleLock lock(DllAvCodec::m_critSection);
    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); };

};
4

1 回答 1

0
extern "C" { 

应该包括你的班级DllAvCodecInterface,像这样:

extern "C" { 
class DllAvCodecInterface
{
    ...
};

class DllAvCodec : public DllAvCodecInterface
{
    ...
}

}  // extern "C"
于 2014-03-21T09:43:45.183 回答