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