1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
#include "codec.h"
#include "common/library.h"
#include "common/strutil.h"
#undef __INTRODUCED_IN
#define __INTRODUCED_IN(...)
#include <media/NdkMediaCodec.h>
static const struct {
const char* mime;
FFCodecType type;
} FF_CODEC_MIME_TO_TYPE[] = {
{ "video/3gpp", FF_CODEC_TYPE_H263 },
{ "video/h263", FF_CODEC_TYPE_H263 },
{ "video/mjpeg", FF_CODEC_TYPE_MJPEG },
{ "video/mpeg2", FF_CODEC_TYPE_MPEG2 },
{ "video/mp2v-es", FF_CODEC_TYPE_MPEG2 },
{ "video/mp4v-es", FF_CODEC_TYPE_DIVX_XVID },
{ "video/avc", FF_CODEC_TYPE_H264 },
{ "video/hevc", FF_CODEC_TYPE_HEVC },
{ "video/x-vnd.on2.vp8", FF_CODEC_TYPE_VP8 },
{ "video/x-vnd.on2.vp9", FF_CODEC_TYPE_VP9 },
{ "video/av01", FF_CODEC_TYPE_AV1 },
{ "video/vvc", FF_CODEC_TYPE_VVC },
};
static bool ffCodecIsLikelySoftware(const char* codecName) {
if (!codecName) {
return true;
}
return ffStrStartsWith(codecName, "OMX.google.") ||
ffStrStartsWith(codecName, "c2.android.") ||
ffStrStartsWith(codecName, "OMX.ffmpeg.") ||
ffStrStartsWith(codecName, "OMX.PV.");
}
static bool ffCodecIsHardwareAccelerated(
AMediaCodec* codec,
__typeof__(&AMediaCodec_getName) ffAMediaCodec_getName,
__typeof__(&AMediaCodec_releaseName) ffAMediaCodec_releaseName) {
if (!codec) {
return false;
}
char* codecName = NULL;
media_status_t status = ffAMediaCodec_getName(codec, &codecName);
if (status != AMEDIA_OK || !codecName) {
return false;
}
bool isHardware = !ffCodecIsLikelySoftware(codecName);
ffAMediaCodec_releaseName(codec, codecName);
return isHardware;
}
const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /*list of FFCodecResult*/) {
FF_LIBRARY_LOAD_MESSAGE(mediandk, "libmediandk.so", 0)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mediandk, AMediaCodec_createDecoderByType)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mediandk, AMediaCodec_createEncoderByType)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mediandk, AMediaCodec_delete)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mediandk, AMediaCodec_getName)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mediandk, AMediaCodec_releaseName)
FFCodecType decoders = FF_CODEC_TYPE_NONE;
FFCodecType encoders = FF_CODEC_TYPE_NONE;
for (uint32_t i = 0; i < ARRAY_SIZE(FF_CODEC_MIME_TO_TYPE); ++i) {
const char* mime = FF_CODEC_MIME_TO_TYPE[i].mime;
FFCodecType type = FF_CODEC_MIME_TO_TYPE[i].type;
if ((options->showType & FF_CODEC_SHOW_TYPE_DECODER) && !(decoders & type)) {
AMediaCodec* decoder = ffAMediaCodec_createDecoderByType(mime);
if (decoder) {
if (ffCodecIsHardwareAccelerated(decoder, ffAMediaCodec_getName, ffAMediaCodec_releaseName)) {
decoders |= type;
}
ffAMediaCodec_delete(decoder);
}
}
if ((options->showType & FF_CODEC_SHOW_TYPE_ENCODER) && !(encoders & type)) {
AMediaCodec* encoder = ffAMediaCodec_createEncoderByType(mime);
if (encoder) {
if (ffCodecIsHardwareAccelerated(encoder, ffAMediaCodec_getName, ffAMediaCodec_releaseName)) {
encoders |= type;
}
ffAMediaCodec_delete(encoder);
}
}
}
if (decoders != FF_CODEC_TYPE_NONE || encoders != FF_CODEC_TYPE_NONE) {
FFCodecResult* item = FF_LIST_ADD(FFCodecResult, *result);
ffStrbufInitStatic(&item->gpu, "Default");
item->decoders = decoders;
item->encoders = encoders;
item->platformApi = "AMediaCodec";
}
return NULL;
}
|