• 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 
16 #include "ffmpeg_track_meta.h"
17 #include "foundation/log.h"
18 #include "utils/constants.h"
19 #include "utils/type_define.h"
20 #include "plugins/ffmpeg_adapter/utils/aac_audio_config_parser.h"
21 #include "plugins/ffmpeg_adapter/utils/ffmpeg_utils.h"
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<AVCodecContext>& context, TagMap& meta);
32 
33 struct StreamConvertor {
34     AVCodecID codecId;
35     ConvertFunc convertor;
36 };
37 
38 StreamConvertor g_streamConvertors[] = {{AV_CODEC_ID_PCM_S16LE, ConvertRawAudioStreamToMetaInfo},
39                                         {AV_CODEC_ID_PCM_S16BE, ConvertRawAudioStreamToMetaInfo},
40                                         {AV_CODEC_ID_PCM_U16LE, ConvertRawAudioStreamToMetaInfo},
41                                         {AV_CODEC_ID_PCM_U16BE, ConvertRawAudioStreamToMetaInfo},
42                                         {AV_CODEC_ID_PCM_S8, ConvertRawAudioStreamToMetaInfo},
43                                         {AV_CODEC_ID_PCM_U8, ConvertRawAudioStreamToMetaInfo},
44                                         {AV_CODEC_ID_MP1, ConvertMP1StreamToMetaInfo},
45                                         {AV_CODEC_ID_MP2, ConvertMP2StreamToMetaInfo},
46                                         {AV_CODEC_ID_MP3, ConvertMP3StreamToMetaInfo},
47                                         {AV_CODEC_ID_AAC, ConvertAACStreamToMetaInfo},
48                                         {AV_CODEC_ID_AAC_LATM, ConvertAACLatmStreamToMetaInfo},
49 #ifdef VIDEO_SUPPORT
50                                         {AV_CODEC_ID_H264, ConvertAVCStreamToMetaInfo}
51 #endif
52 };
53 
IsPcmStream(const AVStream & avStream)54 bool IsPcmStream(const AVStream& avStream)
55 {
56     auto codecId = avStream.codecpar->codec_id;
57     return codecId == AV_CODEC_ID_PCM_S16LE || codecId == AV_CODEC_ID_PCM_S16BE || codecId == AV_CODEC_ID_PCM_U16LE ||
58            codecId == AV_CODEC_ID_PCM_U16BE || codecId == AV_CODEC_ID_PCM_S8 || codecId == AV_CODEC_ID_PCM_U8;
59 }
60 
ConvertCommonAudioStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVCodecContext> & context,TagMap & meta)61 void ConvertCommonAudioStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVCodecContext>& context,
62                                         TagMap& meta)
63 {
64     meta.insert({Tag::TRACK_ID, static_cast<uint32_t>(avStream.index)});
65     if (context->channels != -1) {
66         meta.insert({Tag::AUDIO_SAMPLE_RATE, static_cast<uint32_t>(context->sample_rate)});
67         meta.insert({Tag::AUDIO_CHANNELS, static_cast<uint32_t>(context->channels)});
68         meta.insert(
69             {Tag::AUDIO_CHANNEL_LAYOUT, ConvertChannelLayoutFromFFmpeg(context->channels, context->channel_layout)});
70         // ffmpeg defaults to 1024 samples per frame for planar PCM in each buffer (one for each channel).
71         uint32_t samplesPerFrame = 1024;
72         if (!IsPcmStream(avStream)) {
73             samplesPerFrame = static_cast<uint32_t>(context->frame_size);
74         }
75         meta.insert({Tag::AUDIO_SAMPLE_PER_FRAME, samplesPerFrame});
76         meta.insert({Tag::AUDIO_SAMPLE_FORMAT, Trans2Format(context->sample_fmt)});
77         meta.insert({Tag::MEDIA_BITRATE, static_cast<int64_t>(context->bit_rate)});
78     }
79 }
80 } // namespace
81 
ConvertRawAudioStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVCodecContext> & context,TagMap & meta)82 void ConvertRawAudioStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVCodecContext>& context,
83                                      TagMap& meta)
84 {
85     meta.insert({Tag::MIME, std::string(MEDIA_MIME_AUDIO_RAW)});
86     ConvertCommonAudioStreamToMetaInfo(avStream, context, meta);
87 }
88 
ConvertMP1StreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVCodecContext> & context,TagMap & meta)89 void ConvertMP1StreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVCodecContext>& context, TagMap& meta)
90 {
91     meta.insert({Tag::MIME, std::string(MEDIA_MIME_AUDIO_MPEG)});
92     ConvertCommonAudioStreamToMetaInfo(avStream, context, meta);
93     meta.insert({Tag::AUDIO_MPEG_VERSION, static_cast<uint32_t>(1)});
94     meta.insert({Tag::AUDIO_MPEG_LAYER, static_cast<uint32_t>(1)});
95 }
96 
ConvertMP2StreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVCodecContext> & context,TagMap & meta)97 void ConvertMP2StreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVCodecContext>& context, TagMap& meta)
98 {
99     meta.insert({Tag::MIME, std::string(MEDIA_MIME_AUDIO_MPEG)});
100     ConvertCommonAudioStreamToMetaInfo(avStream, context, meta);
101     meta.insert({Tag::AUDIO_MPEG_VERSION, static_cast<uint32_t>(1)});
102     meta.insert({Tag::AUDIO_MPEG_LAYER, static_cast<uint32_t>(2)}); // 2
103 }
104 
ConvertMP3StreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVCodecContext> & context,TagMap & meta)105 void ConvertMP3StreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVCodecContext>& context, TagMap& meta)
106 {
107     meta.insert({Tag::MIME, std::string(MEDIA_MIME_AUDIO_MPEG)});
108     ConvertCommonAudioStreamToMetaInfo(avStream, context, meta);
109     meta.insert({Tag::AUDIO_MPEG_VERSION, static_cast<uint32_t>(1)});
110     meta.insert({Tag::AUDIO_MPEG_LAYER, static_cast<uint32_t>(3)}); // 3
111 }
112 
ConvertAACStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVCodecContext> & context,TagMap & meta)113 void ConvertAACStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVCodecContext>& context, TagMap& meta)
114 {
115     meta.insert({Tag::MIME, std::string(MEDIA_MIME_AUDIO_AAC)});
116     ConvertCommonAudioStreamToMetaInfo(avStream, context, meta);
117     meta.insert({Tag::AUDIO_MPEG_VERSION, static_cast<uint32_t>(4)}); // 4
118     meta.insert({Tag::AUDIO_AAC_PROFILE, AudioAacProfile::LC});
119     if (context->extradata_size > 0) {
120         std::vector<uint8_t> codecConfig;
121         codecConfig.assign(context->extradata, context->extradata + context->extradata_size);
122         meta.insert({Tag::MEDIA_CODEC_CONFIG, std::move(codecConfig)});
123         AACAudioConfigParser parser(context->extradata, context->extradata_size);
124         if (!parser.ParseConfigs()) {
125             return;
126         }
127         meta.insert({Tag::AUDIO_AAC_LEVEL, parser.GetLevel()});
128         auto profile = parser.GetProfile();
129         if (profile != AudioAacProfile::NONE) {
130             meta.insert({Tag::AUDIO_AAC_PROFILE, profile});
131         }
132     } else {
133         meta.insert({Tag::AUDIO_AAC_STREAM_FORMAT, AudioAacStreamFormat::MP4ADTS});
134     }
135 }
136 
ConvertAACLatmStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVCodecContext> & context,TagMap & meta)137 void ConvertAACLatmStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVCodecContext>& context,
138                                     TagMap& meta)
139 {
140     meta.insert({Tag::MIME, std::string(MEDIA_MIME_AUDIO_AAC_LATM)});
141     meta.insert({Tag::TRACK_ID, static_cast<uint32_t>(avStream.index)});
142     if (context->channels != -1) {
143         meta.insert({Tag::AUDIO_SAMPLE_RATE, static_cast<uint32_t>(context->sample_rate)});
144         meta.insert({Tag::AUDIO_CHANNELS, static_cast<uint32_t>(context->channels)});
145         meta.insert({Tag::AUDIO_SAMPLE_FORMAT, Trans2Format(context->sample_fmt)});
146         meta.insert(
147             {Tag::AUDIO_CHANNEL_LAYOUT, ConvertChannelLayoutFromFFmpeg(context->channels, context->channel_layout)});
148         meta.insert({Tag::AUDIO_SAMPLE_PER_FRAME, static_cast<uint32_t>(context->frame_size)});
149         meta.insert({Tag::MEDIA_BITRATE, static_cast<int64_t>(context->bit_rate)});
150     }
151     meta.insert({Tag::AUDIO_MPEG_VERSION, static_cast<uint32_t>(4)}); // 4
152     meta.insert({Tag::AUDIO_AAC_STREAM_FORMAT, AudioAacStreamFormat::MP4LOAS});
153 }
154 
155 #ifdef VIDEO_SUPPORT
ConvertAVCStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVCodecContext> & context,TagMap & meta)156 void ConvertAVCStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVCodecContext>& context, TagMap& meta)
157 {
158     meta.insert({Tag::MIME, std::string(MEDIA_MIME_VIDEO_AVC)});
159     meta.insert({Tag::TRACK_ID, static_cast<uint32_t>(avStream.index)});
160     meta.insert({Tag::MEDIA_BITRATE, context->bit_rate});
161     meta.insert({Tag::VIDEO_WIDTH, static_cast<uint32_t>(context->width)});
162     meta.insert({Tag::VIDEO_HEIGHT, static_cast<uint32_t>(context->height)});
163     if (context->extradata_size > 0) {
164         AVCConfigDataParser parser(context->extradata, context->extradata_size);
165         if (!parser.ParseConfigData()) {
166             return;
167         }
168         std::shared_ptr<uint8_t> cfgData = nullptr;
169         size_t cfgDataSize = 0;
170         if (parser.GetNewConfigData(cfgData, cfgDataSize) && (cfgData != nullptr) && (cfgDataSize != 0)) {
171             std::vector<uint8_t> codecConfig;
172             codecConfig.assign(cfgData.get(), cfgData.get() + cfgDataSize);
173             meta.insert({Tag::MEDIA_CODEC_CONFIG, std::move(codecConfig)});
174         }
175     }
176 }
177 #endif
178 
ConvertAVStreamToMetaInfo(const AVStream & avStream,const std::shared_ptr<AVCodecContext> & context,TagMap & meta)179 void ConvertAVStreamToMetaInfo(const AVStream& avStream, const std::shared_ptr<AVCodecContext>& context, TagMap& meta)
180 {
181     meta.clear();
182     auto codecId = avStream.codecpar->codec_id;
183     for (auto& streamConvertor : g_streamConvertors) {
184         if (streamConvertor.codecId == codecId) {
185             streamConvertor.convertor(avStream, context, meta);
186             return;
187         }
188     }
189     MEDIA_LOG_E("unsupported codec id: %" PUBLIC_LOG "d", codecId);
190 }
191 } // namespace Ffmpeg
192 } // namespace Plugin
193 } // namespace Media
194 } // namespace OHOS
195