FFMPEG avcodec_parameters_copy Android 上崩溃

ffmpeg avcodec_parameters_copy crash on android

提问人:徐同鹏 提问时间:10/25/2023 更新时间:11/9/2023 访问量:19

问:

我是新手,我正在尝试用 Android ffmpeg 创建一个多路复用器应用程序,所以我通过 Ubuntu 编译 .so lib:

API=21
CPU=armv8-a
ARCH=arm64
PREFIX=$(pwd)/android/$CPU/$ARCH
TOOLCHAIN=/root/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
SYSROOT=$TOOLCHAIN/sysroot
OPTIMIZE_CFLAGS="-march=$CPU"

./configure \
        --prefix=$PREFIX \
        --arch=$ARCH \
        --cpu=$CPU \
        --cross-prefix=$CROSS_PREFIX \
        --cc=$CC \
        --cxx=$CXX \
        --sysroot=$SYSROOT \
        --extra-cflags="-Os -fPIC $OPTIMIZE_CFLAGS" \
        --target-os=android \
        --enable-cross-compile \
        --disable-gpl \
        --enable-shared \
        --disable-static \
        --disable-programs \
        --disable-ffmpeg \
        --disable-ffplay \
        --disable-ffprobe \
        --disable-doc \
        --disable-htmlpages \
        --disable-manpages \
        --disable-txtpages

我还得到了一些 MUXER 的 C++ 代码片段:

#include <jni.h>
#include <string>
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <stdio.h>

using namespace std;

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
#include <libswresample/swresample.h>
}

//cout
#ifndef LOG_TAG
#define LOG_TAG "recite.debug"
#include <android/log.h>
#define debug(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#endif
//cout

string jstringToStdString(JNIEnv* env, jstring jstr) {
    if (jstr == NULL) {
        return "";
    }
    char* chars = (char*)env->GetStringUTFChars(jstr, NULL);
    string ret(chars);
    env->ReleaseStringUTFChars(jstr, chars);
    return ret;
}

void FFMPEG_Callback(void* ptr, int level, const char* fmt, va_list vl)
{
    //if(level != 32) return;
    char buffer[1024];
    vsprintf(buffer, fmt, vl);
    debug("msg : [%d] %s", level, buffer);
}

//Java_com_example_recite_display_tabs_Setting_run
extern "C" JNIEXPORT int JNICALL
Java_com_example_recite_util_Bilibili_compose(JNIEnv * env, jclass obj, jstring audioSrc, jstring videoSrc, jstring dest)
{
    int ret;
    av_log_set_callback(&FFMPEG_Callback);
    //    const char* input_video_file_name = "payphone.mp4";
    //    const char* input_audio_file_name = "payphone.mp3";
    //    const char* output_file_name = "out.mp4";
    const char* input_audio_file_name = (const char*)env->GetStringUTFChars(audioSrc, NULL);
    const char* input_video_file_name = (const char*)env->GetStringUTFChars(videoSrc, NULL);
    const char* output_file_name = (const char*)env->GetStringUTFChars(dest, NULL);

    debug("video src: %s", input_video_file_name);
    debug("audio src: %s", input_audio_file_name);
    debug("dest src: %s", output_file_name);

    AVFormatContext* ifmt_ctx_v = NULL, * ifmt_ctx_a = NULL;
    AVFormatContext* ofmt_ctx = NULL;

    int in_stream_index_v = -1;
    int in_stream_index_a = -1;

    int out_stream_index_v = -1;
    int out_stream_index_a = -1;

    debug("<--------------- input file info --------------->\n");

    if ((ret = avformat_open_input(&ifmt_ctx_v, input_video_file_name, NULL, NULL)) < 0) {
        debug("Cannot open input file\n");
        return ret;
    }
    if ((ret = avformat_find_stream_info(ifmt_ctx_v, NULL)) < 0) {
        debug("Cannot find stream information\n");
        return ret;
    }
    ret = av_find_best_stream(ifmt_ctx_v, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
    if (ret < 0) {
        debug("Cannot find video stream\n");
        return ret;
    }
    in_stream_index_v = ret;
    av_dump_format(ifmt_ctx_v, 0, input_video_file_name, 0);

    if ((ret = avformat_open_input(&ifmt_ctx_a, input_audio_file_name, NULL, NULL)) < 0) {
        debug("Cannot open input file\n");
        return ret;
    }
    if ((ret = avformat_find_stream_info(ifmt_ctx_a, NULL)) < 0) {
        debug("Cannot find stream information\n");
        return ret;
    }
    ret = av_find_best_stream(ifmt_ctx_a, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    if (ret < 0) {
        debug("Cannot find audio stream\n");
        return ret;
    }
    in_stream_index_a = ret;
    av_dump_format(ifmt_ctx_a, 0, input_audio_file_name, 0);

    ret = avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, output_file_name);
    if (ret < 0) {
        debug("Cannot open output file\n");
        return ret;
    }
    if (in_stream_index_v >= 0) {
        AVStream* in_stream = ifmt_ctx_v->streams[in_stream_index_v];
        AVStream* out_stream = avformat_new_stream(ofmt_ctx, NULL);
        debug("\n<--------------- crash begin --------------->\n");
** //the code crashes here on android **
***     ret = avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar);***
        debug("\n<--------------- crash end --------------->\n");
        out_stream->codecpar->codec_tag = 0;

        out_stream_index_v = out_stream->index;
    }


// blah...blah...

我已经重建了两次.so lib,它不起作用。 谁能告诉我为什么代码在Linux(pc)上运行良好,但在Android上却崩溃了? 而且我真的不确定如何在 Android 中调试 C++ 代码......任何帮助将不胜感激,提前TKS!!

Android Linux Ubuntu FFMPEG 交叉编译

评论


答:

0赞 徐同鹏 11/9/2023 #1

我意识到我错过了 cmakeList.txt 文件中 avdevice.so 库。所以,在我将其添加到编译中后,它工作得很好。