1 /*
2 * Copyright (c) 2021-2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #define HST_LOG_TAG "FfmpegTrackMeta"
16 #include "ffmpeg_track_meta.h"
17 #include "foundation/log.h"
18 #include "foundation/utils/constants.h"
19 #include "plugins/ffmpeg_adapter/utils/aac_audio_config_parser.h"
20 #include "plugins/ffmpeg_adapter/utils/ffmpeg_utils.h"
21
22 #ifdef VIDEO_SUPPORT
23 #include "plugins/ffmpeg_adapter/utils/avc_config_data_parser.h"
24 #endif
25
26 namespace OHOS {
27 namespace Media {
28 namespace Plugin {
29 namespace Ffmpeg {
30 namespace {
31 using ConvertFunc = void (*)(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
32 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta);
33
34 struct StreamConvertor {
35 AVCodecID codecId;
36 ConvertFunc convertor;
37 };
38
39 StreamConvertor g_streamConvertors[] = {{AV_CODEC_ID_PCM_S16LE, ConvertRawAudioStreamToMetaInfo},
40 {AV_CODEC_ID_PCM_S16BE, ConvertRawAudioStreamToMetaInfo},
41 {AV_CODEC_ID_PCM_U16LE, ConvertRawAudioStreamToMetaInfo},
42 {AV_CODEC_ID_PCM_U16BE, ConvertRawAudioStreamToMetaInfo},
43 {AV_CODEC_ID_PCM_S24LE, ConvertRawAudioStreamToMetaInfo},
44 {AV_CODEC_ID_PCM_F32LE, ConvertRawAudioStreamToMetaInfo},
45 {AV_CODEC_ID_PCM_S8, ConvertRawAudioStreamToMetaInfo},
46 {AV_CODEC_ID_PCM_U8, ConvertRawAudioStreamToMetaInfo},
47 {AV_CODEC_ID_MP1, ConvertMP1StreamToMetaInfo},
48 {AV_CODEC_ID_MP2, ConvertMP2StreamToMetaInfo},
49 {AV_CODEC_ID_MP3, ConvertMP3StreamToMetaInfo},
50 {AV_CODEC_ID_AAC, ConvertAACStreamToMetaInfo},
51 {AV_CODEC_ID_AAC_LATM, ConvertAACLatmStreamToMetaInfo},
52 {AV_CODEC_ID_VORBIS, ConvertVorbisStreamToMetaInfo},
53 {AV_CODEC_ID_FLAC, ConvertFLACStreamToMetaInfo},
54 {AV_CODEC_ID_APE, ConvertAPEStreamToMetaInfo},
55 #ifdef AVS3DA_SUPPORT
56 {AV_CODEC_ID_AVS3DA, ConvertAVS3DAStreamToMetaInfo},
57 #endif
58 #ifdef VIDEO_SUPPORT
59 {AV_CODEC_ID_H264, ConvertAVCStreamToMetaInfo},
60 #endif
61 {AV_CODEC_ID_AMR_NB, ConvertAMRnbStreamToMetaInfo},
62 {AV_CODEC_ID_AMR_WB, ConvertAMRwbStreamToMetaInfo},
63 };
64
IsPcmStream(const AVStream & avStream)65 bool IsPcmStream(const AVStream& avStream)
66 {
67 auto codecId = avStream.codecpar->codec_id;
68 return codecId == AV_CODEC_ID_PCM_S16LE || codecId == AV_CODEC_ID_PCM_S16BE || codecId == AV_CODEC_ID_PCM_U16LE ||
69 codecId == AV_CODEC_ID_PCM_U16BE || codecId == AV_CODEC_ID_PCM_S8 || codecId == AV_CODEC_ID_PCM_U8 ||
70 codecId == AV_CODEC_ID_PCM_F32LE;
71 }
72
ConvertCommonTrackToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)73 void ConvertCommonTrackToMetaInfo(const AVStream& avStream,
74 const std::shared_ptr<AVFormatContext>& avFormatContext,
75 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
76 {
77 meta.Set<Tag::TRACK_ID>(avStream.index);
78 meta.Set<Tag::MEDIA_DURATION>(
79 ConvertTimeFromFFmpeg(avStream.duration, avStream.time_base));
80 meta.Set<Tag::MEDIA_START_TIME>(
81 ConvertTimeFromFFmpeg(avStream.start_time, avStream.time_base));
82 if (avCodecContext->extradata_size > 0) {
83 CodecConfig codecConfig;
84 codecConfig.assign(avCodecContext->extradata, avCodecContext->extradata + avCodecContext->extradata_size);
85 meta.Set<Tag::MEDIA_CODEC_CONFIG>(std::move(codecConfig));
86 }
87 int64_t bitRate = avCodecContext->bit_rate;
88 if (!bitRate) {
89 bitRate = avFormatContext->bit_rate;
90 }
91 FALSE_LOG(meta.Set<Tag::MEDIA_BITRATE>(bitRate));
92 FALSE_LOG(meta.Set<Tag::BITS_PER_CODED_SAMPLE>(avCodecContext->bits_per_coded_sample));
93 }
94
95 #ifdef VIDEO_SUPPORT
ConvertCommonVideoTrackToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)96 void ConvertCommonVideoTrackToMetaInfo(const AVStream& avStream,
97 const std::shared_ptr<AVFormatContext>& avFormatContext,
98 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
99 {
100 ConvertCommonTrackToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
101 meta.Set<Tag::VIDEO_WIDTH>(avCodecContext->width);
102 meta.Set<Tag::VIDEO_HEIGHT>(avCodecContext->height);
103 uint32_t frameRate = 0;
104 if (avStream.avg_frame_rate.den) {
105 static constexpr int32_t factor = 100;
106 frameRate = static_cast<uint32_t>(
107 static_cast<float>(avStream.avg_frame_rate.num) / avStream.avg_frame_rate.den * factor);
108 }
109 meta.Set<Tag::VIDEO_FRAME_RATE>(frameRate);
110 }
111 #endif
112
ConvertCommonAudioStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)113 void ConvertCommonAudioStreamToMetaInfo(const AVStream& avStream,
114 const std::shared_ptr<AVFormatContext>& avFormatContext,
115 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
116 {
117 ConvertCommonTrackToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
118 if (avCodecContext->channels != -1) {
119 meta.Set<Tag::AUDIO_SAMPLE_RATE>(avCodecContext->sample_rate);
120 meta.Set<Tag::AUDIO_CHANNELS>(avCodecContext->channels);
121 meta.Set<Tag::AUDIO_CHANNEL_LAYOUT>(ConvertChannelLayoutFromFFmpeg(avCodecContext->channels,
122 avCodecContext->channel_layout));
123 // ffmpeg defaults to 1024 samples per frame for planar PCM in each buffer (one for each channel).
124 uint32_t samplesPerFrame = 1024;
125 if (!IsPcmStream(avStream) && avCodecContext->frame_size != 0) {
126 samplesPerFrame = static_cast<uint32_t>(avCodecContext->frame_size);
127 }
128 meta.Set<Tag::AUDIO_SAMPLE_PER_FRAME>(samplesPerFrame);
129 if (avCodecContext->sample_fmt != AV_SAMPLE_FMT_NONE) {
130 meta.Set<Tag::AUDIO_SAMPLE_FORMAT>(ConvFf2PSampleFmt(avCodecContext->sample_fmt));
131 } else {
132 meta.Set<Tag::AUDIO_SAMPLE_FORMAT>(AudioSampleFormat::S16);
133 }
134 }
135 }
136 } // namespace
137
ConvertRawAudioStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)138 void ConvertRawAudioStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
139 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
140 {
141 meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_RAW);
142 ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
143 }
144
ConvertMP1StreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)145 void ConvertMP1StreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
146 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
147 {
148 meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_MPEG);
149 ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
150 meta.Set<Tag::AUDIO_MPEG_VERSION>(1);
151 meta.Set<Tag::AUDIO_MPEG_LAYER>(1);
152 }
153
ConvertMP2StreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)154 void ConvertMP2StreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
155 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
156 {
157 meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_MPEG);
158 ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
159 meta.Set<Tag::AUDIO_MPEG_VERSION>(1);
160 meta.Set<Tag::AUDIO_MPEG_LAYER>(2); // 2
161 }
162
ConvertMP3StreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)163 void ConvertMP3StreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
164 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
165 {
166 meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_MPEG);
167 ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
168 meta.Set<Tag::AUDIO_MPEG_VERSION>(1);
169 meta.Set<Tag::AUDIO_MPEG_LAYER>(3); // 3
170 }
171
ConvertFLACStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)172 void ConvertFLACStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
173 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
174 {
175 meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_FLAC);
176 ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
177 }
178
ConvertAPEStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)179 void ConvertAPEStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
180 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
181 {
182 meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_APE);
183 ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
184 }
185
ConvertAMRnbStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)186 void ConvertAMRnbStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
187 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
188 {
189 meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_AMR_NB);
190 ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
191 }
192
ConvertAMRwbStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)193 void ConvertAMRwbStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
194 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
195 {
196 meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_AMR_WB);
197 ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
198 }
199
ConvertVorbisStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)200 void ConvertVorbisStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
201 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
202 {
203 meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_VORBIS);
204 ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
205 }
206
ConvertAACStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)207 void ConvertAACStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
208 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
209 {
210 meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_AAC);
211 ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
212 meta.Set<Tag::AUDIO_MPEG_VERSION>(4); // 4
213 meta.Set<Tag::AUDIO_AAC_PROFILE>(AudioAacProfile::LC);
214 if (avCodecContext->extradata_size > 0) {
215 std::vector<uint8_t> codecConfig;
216 codecConfig.assign(avCodecContext->extradata, avCodecContext->extradata + avCodecContext->extradata_size);
217 meta.Set<Tag::MEDIA_CODEC_CONFIG>(std::move(codecConfig));
218 AACAudioConfigParser parser(avCodecContext->extradata, avCodecContext->extradata_size);
219 if (!parser.ParseConfigs()) {
220 return;
221 }
222 meta.Set<Tag::AUDIO_AAC_LEVEL>(parser.GetLevel());
223 auto profile = parser.GetProfile();
224 if (profile != AudioAacProfile::NONE) {
225 meta.Set<Tag::AUDIO_AAC_PROFILE>(profile);
226 }
227 } else {
228 meta.Set<Tag::AUDIO_AAC_STREAM_FORMAT>(AudioAacStreamFormat::MP4ADTS);
229 }
230 }
231
ConvertAACLatmStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)232 void ConvertAACLatmStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
233 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
234 {
235 meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_AAC_LATM);
236 ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
237 meta.Set<Tag::AUDIO_MPEG_VERSION>(4); // 4
238 meta.Set<Tag::AUDIO_AAC_STREAM_FORMAT>(AudioAacStreamFormat::MP4LOAS);
239 meta.Set<Tag::BITS_PER_CODED_SAMPLE>(avCodecContext->bits_per_coded_sample);
240 }
241
242 #ifdef AVS3DA_SUPPORT
ConvertAVS3DAStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)243 void ConvertAVS3DAStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
244 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
245 {
246 meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_AVS3DA);
247 ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
248 }
249 #endif
250
251 #ifdef VIDEO_SUPPORT
ConvertAVCStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)252 void ConvertAVCStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
253 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
254 {
255 meta.Set<Tag::MIME>(MEDIA_MIME_VIDEO_H264);
256 ConvertCommonVideoTrackToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
257 if (avCodecContext->extradata_size > 0) {
258 AVCConfigDataParser parser(avCodecContext->extradata, avCodecContext->extradata_size);
259 if (!parser.ParseConfigData()) {
260 return;
261 }
262 std::shared_ptr<uint8_t> cfgData = nullptr;
263 size_t cfgDataSize = 0;
264 if (parser.GetNewConfigData(cfgData, cfgDataSize) && (cfgData != nullptr) && (cfgDataSize != 0)) {
265 std::vector<uint8_t> codecConfig;
266 codecConfig.assign(cfgData.get(), cfgData.get() + cfgDataSize);
267 meta.Set<Tag::MEDIA_CODEC_CONFIG>(std::move(codecConfig));
268 }
269 }
270 }
271 #endif
ConvertAVStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)272 void ConvertAVStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
273 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
274 {
275 meta.Clear();
276 auto codecId = avStream.codecpar->codec_id;
277 for (auto& streamConvertor : g_streamConvertors) {
278 if (streamConvertor.codecId == codecId) {
279 streamConvertor.convertor(avStream, avFormatContext, avCodecContext, meta);
280 return;
281 }
282 }
283 MEDIA_LOG_E("unsupported codec id: " PUBLIC_LOG_D32 ", name: " PUBLIC_LOG_S, codecId, avcodec_get_name(codecId));
284 }
285 } // namespace Ffmpeg
286 } // namespace Plugin
287 } // namespace Media
288 } // namespace OHOS
289