• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                                         {AV_CODEC_ID_OPUS, ConvertOPUSStreamToMetaInfo},
64 };
65 
IsPcmStream(const AVStream & avStream)66 bool IsPcmStream(const AVStream& avStream)
67 {
68     auto codecId = avStream.codecpar->codec_id;
69     return codecId == AV_CODEC_ID_PCM_S16LE || codecId == AV_CODEC_ID_PCM_S16BE || codecId == AV_CODEC_ID_PCM_U16LE ||
70            codecId == AV_CODEC_ID_PCM_U16BE || codecId == AV_CODEC_ID_PCM_S8 || codecId == AV_CODEC_ID_PCM_U8 ||
71            codecId == AV_CODEC_ID_PCM_F32LE;
72 }
73 
ConvertCommonTrackToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)74 void ConvertCommonTrackToMetaInfo(const AVStream& avStream,
75                                   const std::shared_ptr<AVFormatContext>& avFormatContext,
76                                   const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
77 {
78     meta.Set<Tag::TRACK_ID>(avStream.index);
79     meta.Set<Tag::MEDIA_DURATION>(
80             ConvertTimeFromFFmpeg(avStream.duration, avStream.time_base));
81     meta.Set<Tag::MEDIA_START_TIME>(
82             ConvertTimeFromFFmpeg(avStream.start_time, avStream.time_base));
83     if (avCodecContext->extradata_size > 0) {
84         CodecConfig codecConfig;
85         codecConfig.assign(avCodecContext->extradata, avCodecContext->extradata + avCodecContext->extradata_size);
86         meta.Set<Tag::MEDIA_CODEC_CONFIG>(std::move(codecConfig));
87     }
88     int64_t bitRate = avCodecContext->bit_rate;
89     if (!bitRate) {
90         bitRate = avFormatContext->bit_rate;
91     }
92     FALSE_LOG(meta.Set<Tag::MEDIA_BITRATE>(bitRate));
93     FALSE_LOG(meta.Set<Tag::BITS_PER_CODED_SAMPLE>(avCodecContext->bits_per_coded_sample));
94 }
95 
96 #ifdef VIDEO_SUPPORT
ConvertCommonVideoTrackToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)97 void ConvertCommonVideoTrackToMetaInfo(const AVStream& avStream,
98                                        const std::shared_ptr<AVFormatContext>& avFormatContext,
99                                        const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
100 {
101     ConvertCommonTrackToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
102     meta.Set<Tag::VIDEO_WIDTH>(avCodecContext->width);
103     meta.Set<Tag::VIDEO_HEIGHT>(avCodecContext->height);
104     uint32_t frameRate = 0;
105     if (avStream.avg_frame_rate.den) {
106         static constexpr int32_t factor = 100;
107         frameRate = static_cast<uint32_t>(
108             static_cast<float>(avStream.avg_frame_rate.num) / avStream.avg_frame_rate.den * factor);
109     }
110     meta.Set<Tag::VIDEO_FRAME_RATE>(frameRate);
111 }
112 #endif
113 
ConvertCommonAudioStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)114 void ConvertCommonAudioStreamToMetaInfo(const AVStream& avStream,
115                                         const std::shared_ptr<AVFormatContext>& avFormatContext,
116                                         const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
117 {
118     ConvertCommonTrackToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
119     if (avCodecContext->channels != -1) {
120         meta.Set<Tag::AUDIO_SAMPLE_RATE>(avCodecContext->sample_rate);
121         meta.Set<Tag::AUDIO_CHANNELS>(avCodecContext->channels);
122         meta.Set<Tag::AUDIO_CHANNEL_LAYOUT>(ConvertChannelLayoutFromFFmpeg(avCodecContext->channels,
123                                                                            avCodecContext->channel_layout));
124         // ffmpeg defaults to 1024 samples per frame for planar PCM in each buffer (one for each channel).
125         uint32_t samplesPerFrame = 1024;
126         if (!IsPcmStream(avStream) && avCodecContext->frame_size != 0) {
127             samplesPerFrame = static_cast<uint32_t>(avCodecContext->frame_size);
128         }
129         meta.Set<Tag::AUDIO_SAMPLE_PER_FRAME>(samplesPerFrame);
130         if (avCodecContext->sample_fmt != AV_SAMPLE_FMT_NONE) {
131             meta.Set<Tag::AUDIO_SAMPLE_FORMAT>(ConvFf2PSampleFmt(avCodecContext->sample_fmt));
132         } else {
133             meta.Set<Tag::AUDIO_SAMPLE_FORMAT>(AudioSampleFormat::S16);
134         }
135     }
136 }
137 } // namespace
138 
ConvertRawAudioStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)139 void ConvertRawAudioStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
140                                      const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
141 {
142     meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_RAW);
143     ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
144 }
145 
ConvertMP1StreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)146 void ConvertMP1StreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
147                                 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
148 {
149     meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_MPEG);
150     ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
151     meta.Set<Tag::AUDIO_MPEG_VERSION>(1);
152     meta.Set<Tag::AUDIO_MPEG_LAYER>(1);
153 }
154 
ConvertMP2StreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)155 void ConvertMP2StreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
156                                 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
157 {
158     meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_MPEG);
159     ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
160     meta.Set<Tag::AUDIO_MPEG_VERSION>(1);
161     meta.Set<Tag::AUDIO_MPEG_LAYER>(2); // 2
162 }
163 
ConvertMP3StreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)164 void ConvertMP3StreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
165                                 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
166 {
167     meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_MPEG);
168     ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
169     meta.Set<Tag::AUDIO_MPEG_VERSION>(1);
170     meta.Set<Tag::AUDIO_MPEG_LAYER>(3); // 3
171 }
172 
ConvertFLACStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)173 void ConvertFLACStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
174                                  const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
175 {
176     meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_FLAC);
177     ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
178 }
179 
ConvertAPEStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)180 void ConvertAPEStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
181                                 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
182 {
183     meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_APE);
184     ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
185 }
186 
ConvertAMRnbStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)187 void ConvertAMRnbStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
188                                   const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
189 {
190     meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_AMR_NB);
191     ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
192 }
193 
ConvertAMRwbStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)194 void ConvertAMRwbStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
195                                   const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
196 {
197     meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_AMR_WB);
198     ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
199 }
200 
ConvertOPUSStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)201 void ConvertOPUSStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
202                                   const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
203 {
204     meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_OPUS);
205     ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
206 }
207 
ConvertVorbisStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)208 void ConvertVorbisStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
209                                    const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
210 {
211     meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_VORBIS);
212     ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
213 }
214 
ConvertAACStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)215 void ConvertAACStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
216                                 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
217 {
218     meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_AAC);
219     ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
220     meta.Set<Tag::AUDIO_MPEG_VERSION>(4); // 4
221     meta.Set<Tag::AUDIO_AAC_PROFILE>(AudioAacProfile::LC);
222     if (avCodecContext->extradata_size > 0) {
223         std::vector<uint8_t> codecConfig;
224         codecConfig.assign(avCodecContext->extradata, avCodecContext->extradata + avCodecContext->extradata_size);
225         meta.Set<Tag::MEDIA_CODEC_CONFIG>(std::move(codecConfig));
226         AACAudioConfigParser parser(avCodecContext->extradata, avCodecContext->extradata_size);
227         if (!parser.ParseConfigs()) {
228             return;
229         }
230         meta.Set<Tag::AUDIO_AAC_LEVEL>(parser.GetLevel());
231         auto profile = parser.GetProfile();
232         if (profile != AudioAacProfile::NONE) {
233             meta.Set<Tag::AUDIO_AAC_PROFILE>(profile);
234         }
235     } else {
236         meta.Set<Tag::AUDIO_AAC_STREAM_FORMAT>(AudioAacStreamFormat::MP4ADTS);
237     }
238 }
239 
ConvertAACLatmStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)240 void ConvertAACLatmStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
241                                     const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
242 {
243     meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_AAC_LATM);
244     ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
245     meta.Set<Tag::AUDIO_MPEG_VERSION>(4); // 4
246     meta.Set<Tag::AUDIO_AAC_STREAM_FORMAT>(AudioAacStreamFormat::MP4LOAS);
247     meta.Set<Tag::BITS_PER_CODED_SAMPLE>(avCodecContext->bits_per_coded_sample);
248 }
249 
250 #ifdef AVS3DA_SUPPORT
ConvertAVS3DAStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)251 void ConvertAVS3DAStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
252                                    const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
253 {
254     meta.Set<Tag::MIME>(MEDIA_MIME_AUDIO_AVS3DA);
255     ConvertCommonAudioStreamToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
256 }
257 #endif
258 
259 #ifdef VIDEO_SUPPORT
ConvertAVCStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)260 void ConvertAVCStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
261                                 const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
262 {
263     meta.Set<Tag::MIME>(MEDIA_MIME_VIDEO_H264);
264     ConvertCommonVideoTrackToMetaInfo(avStream, avFormatContext, avCodecContext, meta);
265     if (avCodecContext->extradata_size > 0) {
266         AVCConfigDataParser parser(avCodecContext->extradata, avCodecContext->extradata_size);
267         if (!parser.ParseConfigData()) {
268             return;
269         }
270         std::shared_ptr<uint8_t> cfgData = nullptr;
271         size_t cfgDataSize = 0;
272         if (parser.GetNewConfigData(cfgData, cfgDataSize) && (cfgData != nullptr) && (cfgDataSize != 0)) {
273             std::vector<uint8_t> codecConfig;
274             codecConfig.assign(cfgData.get(), cfgData.get() + cfgDataSize);
275             meta.Set<Tag::MEDIA_CODEC_CONFIG>(std::move(codecConfig));
276         }
277     }
278 }
279 #endif
ConvertAVStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVFormatContext> & avFormatContext,const std::shared_ptr<AVCodecContext> & avCodecContext,Meta & meta)280 void ConvertAVStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVFormatContext>& avFormatContext,
281                                const std::shared_ptr<AVCodecContext>& avCodecContext, Meta& meta)
282 {
283     meta.Clear();
284     auto codecId = avStream.codecpar->codec_id;
285     for (auto& streamConvertor : g_streamConvertors) {
286         if (streamConvertor.codecId == codecId) {
287             streamConvertor.convertor(avStream, avFormatContext, avCodecContext, meta);
288             return;
289         }
290     }
291     MEDIA_LOG_E("unsupported codec id: " PUBLIC_LOG_D32 ", name: " PUBLIC_LOG_S, codecId, avcodec_get_name(codecId));
292 }
293 } // namespace Ffmpeg
294 } // namespace Plugin
295 } // namespace Media
296 } // namespace OHOS
297