您好,看到你的帖子非常高兴,因为我遇到了和你一样的问题,我也是在ffmpeg 用mediacode硬解编译ndk工程,然后放在硬解出来的纹理给unity,然后avcodec_get_hw_config返回的config是nullptr.看到你的帖子之后,尝试按照https://ffmpeg.org/doxygen/3.4/demuxing_decoding_8c-example.html。然后还是在avcodec_open2失败了,
static int open_codec_context(int *stream_idx,
AVCodecContext **dec_ctx, AVFormatContext *fmt_ctx, enum AVMediaType type)
{
int ret, stream_index;
AVStream *st;
AVCodec *dec = NULL;
AVDictionary *opts = NULL;
ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
if (ret < 0) {
LOGD("Could not find %s stream in input file '%s'\n", av_get_media_type_string(type));
return ret;
} else {
stream_index = ret;
st = fmt_ctx->streams[stream_index];
/* find decoder for the stream */
//dec = avcodec_find_decoder(st->codecpar->codec_id);
dec = avcodec_find_decoder_by_name("h264_mediacodec");
if (!dec) {
LOGD("Failed to find %s codec\n", av_get_media_type_string(type));
return AVERROR(EINVAL);
}
/* Allocate a codec context for the decoder */
*dec_ctx = avcodec_alloc_context3(dec);
if (!*dec_ctx) {
LOGD("Failed to allocate the %s codec context\n",
av_get_media_type_string(type));
return AVERROR(ENOMEM);
}
/* Copy codec parameters from input stream to output codec context */
if ((ret = avcodec_parameters_to_context(*dec_ctx, st->codecpar)) < 0) {
LOGD("Failed to copy %s codec parameters to decoder context\n",
av_get_media_type_string(type));
return ret;
}
/* Init the decoders, with or without reference counting */
av_dict_set(&opts, "refcounted_frames", refcount ? "1" : "0", 0);
if ((ret = avcodec_open2(*dec_ctx, dec, &opts)) < 0) {
LOGD("Failed to open %d codec\n", ret);
return ret;
}
*stream_idx = stream_index;
}
return 0;
}
static int decodeMainV2()
{
AVFormatContext *input_ctx = NULL;
int video_stream, ret;
AVStream *video = NULL;
AVCodecContext *decoder_ctx = NULL;
AVCodec *decoder = NULL;
AVPacket packet;
enum AVHWDeviceType type;
int i;
av_register_all();
const char *mediacodec = "mediacodec";
type = av_hwdevice_find_type_by_name(mediacodec);
if (type == AV_HWDEVICE_TYPE_NONE) {
LOGD("Device type %s is not supported.\n", mediacodec);
LOGD("Available device types:");
while ((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE)
LOGD(" %s", av_hwdevice_get_type_name(type));
LOGD("\n");
return -1;
}
/* open the input file */
if (avformat_open_input(&input_ctx, mp4_url, NULL, NULL) != 0) {
LOGD("Cannot open input file '%s'\n", mp4_url);
return -1;
}
if (avformat_find_stream_info(input_ctx, NULL) < 0) {
LOGD("Cannot find input stream information.\n");
return -1;
}
if(open_codec_context(&video_stream, &decoder_ctx, input_ctx, AVMEDIA_TYPE_VIDEO)>=0){
LOGD("open_codec_context success");
}else
return -1;
/* actual decoding and dump the raw data */
while (ret >= 0 || ret == -11) {
if ((ret = av_read_frame(input_ctx, &packet)) < 0)
break;
if (video_stream == packet.stream_index)
ret = decode_write(decoder_ctx, &packet);
av_packet_unref(&packet);
}
/* flush the decoder */
packet.data = NULL;
packet.size = 0;
av_packet_unref(&packet);
avcodec_free_context(&decoder_ctx);
avformat_close_input(&input_ctx);
av_buffer_unref(&hw_device_ctx);
return 0;
}
在avcodec_open2 failed
我有认为是我编的库的问题。我的ffmpeg库版本是4.3.3,我在网上找了一份32位的库,仍然是相同的结果,我想问一下你的ffmpeg的库的版本?如果方便的话能不能提供一下你的ffmpeg库(32位),不方便的话没事,我这儿也可以编译,我想确定不是库的问题。如果你在解决这个问题还有那些需要注意的地方也可以指点一下
我想在ndk跑通硬解
1,avcodec_open2 的返回值是什么?代表了什么样的错误?你可以使用 av_make_error_string 这个方法来获取错误原因,确定到底是什么原因导致的 avcodec_open2 失败。
2,怀疑你的库有问题的话,可能是没开启 --enable-mediacodec 这个选项。 我用的 FFmpeg 库也是 32 位,版本貌似是 4.2.2,但这个不是问题的关键。问题的关键是你是否在编译时开启了合适的选项 --enable-mediacodec --enable-decoder=h264_mediacodec,这两个选项好像有一个无效的。
3,即使 avcodec_open2 成功,整个 FFmpeg + MediaCodec 硬解码跑通,感觉效果也不会很理想。我的实验结果是,FFmpeg + MediaCodec 的硬解码结果很糟糕,1080P 的视频在很多情况下解码会出现花屏。所以我后来放弃了使用 FFmpeg + MediaCodec 的方法,转而使用纯 NDKMediaCodec 方法来实现 Android 平台硬解码,具体可参考我的文章https://blog.csdn.net/u014248312/article/details/121970559,里面有一个我的 NDKMediaCodecDemo(https://github.com/Enoch-Liu/NdkMediaCodecDemo) ,你可以参考实现。