1 /*
2  * Copyright (c) 2024 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_api_wrap.h"
17 #include <string>
18 #include <dlfcn.h>
19 #include "log.h"
20 
21 namespace {
22 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FOUNDATION, "HiStreamer"};
23 }
24 
25 namespace OHOS {
26 namespace Media {
27 namespace MediaMonitor {
28 
FFmpegApiWrap()29 FFmpegApiWrap::FFmpegApiWrap()
30 {
31 }
32 
~FFmpegApiWrap()33 FFmpegApiWrap::~FFmpegApiWrap()
34 {
35     Close();
36 }
37 
Open()38 bool FFmpegApiWrap::Open()
39 {
40     bool ret = false;
41     std::string path = "libohosffmpeg.z.so";
42     handler = dlopen(path.c_str(), RTLD_NOW);
43     if (handler == nullptr) {
44         return false;
45     }
46     ret = LoadFormatApi();
47     FALSE_RETURN_V(ret == true, ret);
48     ret = LoadCodecApi();
49     FALSE_RETURN_V(ret == true, ret);
50     ret = LoadUtilsApi();
51     FALSE_RETURN_V(ret == true, ret);
52     ret = LoadResampleApi();
53     FALSE_RETURN_V(ret == true, ret);
54     return ret;
55 }
56 
LoadFormatApi()57 bool FFmpegApiWrap::LoadFormatApi()
58 {
59     foramtAllocOutputFunc = (FormatAllocOutputContextFunc)dlsym(handler, "avformat_alloc_output_context2");
60     FALSE_RETURN_V_MSG_E(foramtAllocOutputFunc != nullptr, false, "load error");
61     formatFreeContextFunc = (FormatFreeContextFunc)dlsym(handler, "avformat_free_context");
62     FALSE_RETURN_V_MSG_E(formatFreeContextFunc != nullptr, false, "load error");
63     formatNewStreamFunc = (FormatNewStreamFunc)dlsym(handler, "avformat_new_stream");
64     FALSE_RETURN_V_MSG_E(formatNewStreamFunc != nullptr, false, "load error");
65     formatFlushFunc = (FormatFlushFunc)dlsym(handler, "avformat_flush");
66     FALSE_RETURN_V_MSG_E(formatFlushFunc != nullptr, false, "load error");
67     formatWriteHeaderFunc = (FormatWriteHeaderFunc)dlsym(handler, "avformat_write_header");
68     FALSE_RETURN_V_MSG_E(formatWriteHeaderFunc != nullptr, false, "load error");
69     formatWriteTrailerFunc = (FormatWriteTrailerFunc)dlsym(handler, "av_write_trailer");
70     FALSE_RETURN_V_MSG_E(formatWriteTrailerFunc != nullptr, false, "load error");
71     ioOpenFunc = (IoOpenFunc)dlsym(handler, "avio_open2");
72     FALSE_RETURN_V_MSG_E(ioOpenFunc != nullptr, false, "load error");
73     ioFlushFunc = (IoFlushFunc)dlsym(handler, "avio_flush");
74     FALSE_RETURN_V_MSG_E(ioFlushFunc != nullptr, false, "load error");
75     ioCloseFunc = (IoCloseFunc)dlsym(handler, "avio_close");
76     FALSE_RETURN_V_MSG_E(ioCloseFunc != nullptr, false, "load error");
77     writeFrameFunc = (FormatWriteFrameFunc)dlsym(handler, "av_interleaved_write_frame");
78     FALSE_RETURN_V_MSG_E(writeFrameFunc != nullptr, false, "load error");
79     return true;
80 }
81 
LoadCodecApi()82 bool FFmpegApiWrap::LoadCodecApi()
83 {
84     codecFindFunc = (CodecFindEncoderFunc)dlsym(handler, "avcodec_find_encoder");
85     FALSE_RETURN_V_MSG_E(codecFindFunc != nullptr, false, "load error");
86     codecAllocFunc = (CodecAllocContextFunc)dlsym(handler, "avcodec_alloc_context3");
87     FALSE_RETURN_V_MSG_E(codecAllocFunc != nullptr, false, "load error");
88     codecFreeContextFunc = (CodecFreeContextFunc)dlsym(handler, "avcodec_free_context");
89     FALSE_RETURN_V_MSG_E(codecFreeContextFunc != nullptr, false, "load error");
90     codecOpenFunc = (CodecOpenFunc)dlsym(handler, "avcodec_open2");
91     FALSE_RETURN_V_MSG_E(codecOpenFunc != nullptr, false, "load error");
92     codecParamFromContextFunc = (CodecParamFromContextFunc)dlsym(handler, "avcodec_parameters_from_context");
93     FALSE_RETURN_V_MSG_E(codecParamFromContextFunc != nullptr, false, "load error");
94     sendFrameFunc = (CodecSendFrameFunc)dlsym(handler, "avcodec_send_frame");
95     FALSE_RETURN_V_MSG_E(sendFrameFunc != nullptr, false, "load error");
96     recvPacketFunc = (CodecRecvPacketFunc)dlsym(handler, "avcodec_receive_packet");
97     FALSE_RETURN_V_MSG_E(recvPacketFunc != nullptr, false, "load error");
98     packetAllocFunc = (PacketAllocFunc)dlsym(handler, "av_packet_alloc");
99     FALSE_RETURN_V_MSG_E(packetAllocFunc != nullptr, false, "load error");
100     packetFreeFunc = (PacketFreeFunc)dlsym(handler, "av_packet_free");
101     FALSE_RETURN_V_MSG_E(packetFreeFunc != nullptr, false, "load error");
102     packetUnrefFunc = (PacketUnrefFunc)dlsym(handler, "av_packet_unref");
103     FALSE_RETURN_V_MSG_E(packetUnrefFunc != nullptr, false, "load error");
104     return true;
105 }
106 
LoadUtilsApi()107 bool FFmpegApiWrap::LoadUtilsApi()
108 {
109     frameAllocFunc = (FrameAllocFunc)dlsym(handler, "av_frame_alloc");
110     FALSE_RETURN_V_MSG_E(frameAllocFunc != nullptr, false, "load error");
111     frameGetBufferFunc = (FrameGetBufferFunc)dlsym(handler, "av_frame_get_buffer");
112     FALSE_RETURN_V_MSG_E(frameGetBufferFunc != nullptr, false, "load error");
113     frameFreeFunc = (FrameFreeFunc)dlsym(handler, "av_frame_free");
114     FALSE_RETURN_V_MSG_E(frameFreeFunc != nullptr, false, "load error");
115     getChannelLayoutFunc = (GetChannelLayoutFunc)dlsym(handler, "av_get_default_channel_layout");
116     FALSE_RETURN_V_MSG_E(getChannelLayoutFunc != nullptr, false, "load error");
117     getBytesPerSampleFunc = (GetBytesPerSampleFunc)dlsym(handler, "av_get_bytes_per_sample");
118     FALSE_RETURN_V_MSG_E(getBytesPerSampleFunc != nullptr, false, "load error");
119     sampleFmtIsPlannarFunc = (SampleFmtIsPlannarFunc)dlsym(handler, "av_sample_fmt_is_planar");
120     FALSE_RETURN_V_MSG_E(sampleFmtIsPlannarFunc != nullptr, false, "load error");
121     return true;
122 }
123 
LoadResampleApi()124 bool FFmpegApiWrap::LoadResampleApi()
125 {
126     swrSetOptsFunc = (SwrSetOptsFunc)dlsym(handler, "swr_alloc_set_opts");
127     FALSE_RETURN_V_MSG_E(swrSetOptsFunc != nullptr, false, "load error");
128     swrAllocFunc = (SwrAllocFunc)dlsym(handler, "swr_alloc");
129     FALSE_RETURN_V_MSG_E(swrAllocFunc != nullptr, false, "load error");
130     swrInitFunc = (SwrInitFunc)dlsym(handler, "swr_init");
131     FALSE_RETURN_V_MSG_E(swrInitFunc != nullptr, false, "load error");
132     swrFreeFunc = (SwrFreeFunc)dlsym(handler, "swr_free");
133     FALSE_RETURN_V_MSG_E(swrFreeFunc != nullptr, false, "load error");
134     swrConvertFunc = (SwrConvertFunc)dlsym(handler, "swr_convert");
135     FALSE_RETURN_V_MSG_E(swrConvertFunc != nullptr, false, "load error");
136     return true;
137 }
138 
Close()139 void FFmpegApiWrap::Close()
140 {
141     if (handler != nullptr) {
142         dlclose(handler);
143         handler = nullptr;
144     }
145 }
146 
CodecFindEncoder(AVCodecID id)147 AVCodec *FFmpegApiWrap::CodecFindEncoder(AVCodecID id)
148 {
149     AVCodec *codec = nullptr;
150     if (codecFindFunc != nullptr) {
151         codec = codecFindFunc(id);
152     }
153     return codec;
154 }
155 
CodecAllocContext(const AVCodec * codec)156 AVCodecContext *FFmpegApiWrap::CodecAllocContext(const AVCodec *codec)
157 {
158     AVCodecContext *context = nullptr;
159     if (codecAllocFunc != nullptr) {
160         context = codecAllocFunc(codec);
161     }
162     return context;
163 }
164 
CodecOpen(AVCodecContext * avctx,const AVCodec * codec,AVDictionary ** options)165 int FFmpegApiWrap::CodecOpen(AVCodecContext *avctx,
166     const AVCodec *codec, AVDictionary **options)
167 {
168     int ret = -1;
169     if (codecOpenFunc != nullptr) {
170         ret = codecOpenFunc(avctx, codec, options);
171     }
172     return ret;
173 }
174 
FormatAllocOutputContext(AVFormatContext ** ctx,const AVOutputFormat * oformat,const char * formatName,const char * filename)175 int FFmpegApiWrap::FormatAllocOutputContext(AVFormatContext **ctx,
176     const AVOutputFormat *oformat, const char *formatName, const char *filename)
177 {
178     int ret = -1;
179     if (foramtAllocOutputFunc != nullptr) {
180         ret = foramtAllocOutputFunc(ctx, oformat, formatName, filename);
181     }
182     return ret;
183 }
184 
FormatNewStream(AVFormatContext * s,const AVCodec * c)185 AVStream *FFmpegApiWrap::FormatNewStream(AVFormatContext *s, const AVCodec *c)
186 {
187     AVStream *stream = nullptr;
188     if (formatNewStreamFunc != nullptr) {
189         stream = formatNewStreamFunc(s, c);
190     }
191     return stream;
192 }
193 
CodecParamFromContext(AVCodecParameters * par,const AVCodecContext * codec)194 int FFmpegApiWrap::CodecParamFromContext(AVCodecParameters *par, const AVCodecContext *codec)
195 {
196     int ret = -1;
197     if (codecParamFromContextFunc != nullptr) {
198         ret = codecParamFromContextFunc(par, codec);
199     }
200     return ret;
201 }
202 
IoOpen(AVIOContext ** s,const char * url,int flags,const AVIOInterruptCB * intCb,AVDictionary ** options)203 int FFmpegApiWrap::IoOpen(AVIOContext **s, const char *url, int flags,
204     const AVIOInterruptCB *intCb, AVDictionary **options)
205 {
206     int ret = -1;
207     if (ioOpenFunc != nullptr) {
208         ret = ioOpenFunc(s, url, flags, intCb, options);
209     }
210     return ret;
211 }
212 
IoFlush(AVIOContext * s)213 void FFmpegApiWrap::IoFlush(AVIOContext *s)
214 {
215     if (ioFlushFunc != nullptr) {
216         ioFlushFunc(s);
217     }
218 }
219 
IoClose(AVIOContext * s)220 int FFmpegApiWrap::IoClose(AVIOContext *s)
221 {
222     int ret = -1;
223     if (ioCloseFunc != nullptr) {
224         ret = ioCloseFunc(s);
225     }
226     return ret;
227 }
228 
FormatWriteHeader(AVFormatContext * s,AVDictionary ** options)229 int FFmpegApiWrap::FormatWriteHeader(AVFormatContext *s, AVDictionary **options)
230 {
231     int ret = -1;
232     if (formatWriteHeaderFunc != nullptr) {
233         ret = formatWriteHeaderFunc(s, options);
234     }
235     return ret;
236 }
237 
FormatWriteTrailer(AVFormatContext * s)238 int FFmpegApiWrap::FormatWriteTrailer(AVFormatContext *s)
239 {
240     int ret = -1;
241     if (formatWriteTrailerFunc != nullptr) {
242         ret = formatWriteTrailerFunc(s);
243     }
244     return ret;
245 }
246 
PacketAlloc()247 AVPacket *FFmpegApiWrap::PacketAlloc()
248 {
249     AVPacket *pkt = nullptr;
250     if (packetAllocFunc != nullptr) {
251         pkt = packetAllocFunc();
252     }
253     return pkt;
254 }
255 
FrameAlloc()256 AVFrame *FFmpegApiWrap::FrameAlloc()
257 {
258     AVFrame *frame = nullptr;
259     if (frameAllocFunc != nullptr) {
260         frame = frameAllocFunc();
261     }
262     return frame;
263 }
264 
FrameGetBuffer(AVFrame * frame,int align)265 int FFmpegApiWrap::FrameGetBuffer(AVFrame *frame, int align)
266 {
267     int ret = -1;
268     if (frameGetBufferFunc != nullptr) {
269         ret = frameGetBufferFunc(frame, align);
270     }
271     return ret;
272 }
273 
CodecSendFrame(AVCodecContext * avctx,const AVFrame * frame)274 int FFmpegApiWrap::CodecSendFrame(AVCodecContext *avctx, const AVFrame *frame)
275 {
276     int ret = -1;
277     if (sendFrameFunc != nullptr) {
278         ret = sendFrameFunc(avctx, frame);
279     }
280     return ret;
281 }
282 
CodecRecvPacket(AVCodecContext * avctx,AVPacket * avpkt)283 int FFmpegApiWrap::CodecRecvPacket(AVCodecContext *avctx, AVPacket *avpkt)
284 {
285     int ret = -1;
286     if (recvPacketFunc != nullptr) {
287         ret = recvPacketFunc(avctx, avpkt);
288     }
289     return ret;
290 }
291 
FormatWriteFrame(AVFormatContext * s,AVPacket * pkt)292 int FFmpegApiWrap::FormatWriteFrame(AVFormatContext *s, AVPacket *pkt)
293 {
294     int ret = -1;
295     if (writeFrameFunc != nullptr) {
296         ret = writeFrameFunc(s, pkt);
297     }
298     return ret;
299 }
300 
FormatFlush(AVFormatContext * s)301 int FFmpegApiWrap::FormatFlush(AVFormatContext *s)
302 {
303     int ret = -1;
304     if (formatFlushFunc != nullptr) {
305         ret = formatFlushFunc(s);
306     }
307     return ret;
308 }
309 
FormatFreeContext(AVFormatContext * s)310 void FFmpegApiWrap::FormatFreeContext(AVFormatContext *s)
311 {
312     if (formatFreeContextFunc != nullptr) {
313         formatFreeContextFunc(s);
314     }
315 }
316 
CodecFreeContext(AVCodecContext ** avctx)317 void FFmpegApiWrap::CodecFreeContext(AVCodecContext **avctx)
318 {
319     if (codecFreeContextFunc != nullptr) {
320         codecFreeContextFunc(avctx);
321     }
322 }
323 
FrameFree(AVFrame ** frame)324 void FFmpegApiWrap::FrameFree(AVFrame **frame)
325 {
326     if (frameFreeFunc != nullptr) {
327         frameFreeFunc(frame);
328     }
329 }
330 
PacketFree(AVPacket ** pkt)331 void FFmpegApiWrap::PacketFree(AVPacket **pkt)
332 {
333     if (packetFreeFunc != nullptr) {
334         packetFreeFunc(pkt);
335     }
336 }
337 
PacketUnref(AVPacket * pkt)338 void FFmpegApiWrap::PacketUnref(AVPacket *pkt)
339 {
340     if (packetUnrefFunc != nullptr) {
341         packetUnrefFunc(pkt);
342     }
343 }
344 
GetChannelLayout(int nbChannels)345 int64_t FFmpegApiWrap::GetChannelLayout(int nbChannels)
346 {
347     int ret = -1;
348     if (getChannelLayoutFunc != nullptr) {
349         ret = getChannelLayoutFunc(nbChannels);
350     }
351     return ret;
352 }
353 
GetBytesPerSample(AVSampleFormat sampleFmt)354 int FFmpegApiWrap::GetBytesPerSample(AVSampleFormat sampleFmt)
355 {
356     int ret = -1;
357     if (getBytesPerSampleFunc != nullptr) {
358         ret = getBytesPerSampleFunc(sampleFmt);
359     }
360     return ret;
361 }
362 
SampleFmtIsPlannar(AVSampleFormat sampleFmt)363 int FFmpegApiWrap::SampleFmtIsPlannar(AVSampleFormat sampleFmt)
364 {
365     int ret = -1;
366     if (sampleFmtIsPlannarFunc != nullptr) {
367         ret = sampleFmtIsPlannarFunc(sampleFmt);
368     }
369     return ret;
370 }
371 
SwrAlloc()372 struct SwrContext *FFmpegApiWrap::SwrAlloc()
373 {
374     struct SwrContext *s = nullptr;
375     if (swrAllocFunc) {
376         s = swrAllocFunc();
377     }
378     return s;
379 }
380 
SwrSetOpts(struct SwrContext * s,int64_t outChLayout,AVSampleFormat outSampleFmt,int outSampleRate,int64_t inChLayout,AVSampleFormat inSampleFmt,int inSampleRate,int logOffset,void * logCtx)381 struct SwrContext *FFmpegApiWrap::SwrSetOpts(struct SwrContext *s,
382     int64_t outChLayout, AVSampleFormat outSampleFmt, int outSampleRate,
383     int64_t inChLayout, AVSampleFormat inSampleFmt, int inSampleRate,
384     int logOffset, void *logCtx)
385 {
386     struct SwrContext *ptr = nullptr;
387     if (swrSetOptsFunc != nullptr) {
388         ptr = swrSetOptsFunc(s,
389                             outChLayout, outSampleFmt, outSampleRate,
390                             inChLayout, inSampleFmt, inSampleRate,
391                             logOffset, logCtx);
392     }
393     return ptr;
394 }
395 
SwrInit(struct SwrContext * s)396 int FFmpegApiWrap::SwrInit(struct SwrContext *s)
397 {
398     int ret = -1;
399     if (swrInitFunc != nullptr) {
400         ret = swrInitFunc(s);
401     }
402     return ret;
403 }
404 
SwrFree(struct SwrContext ** s)405 void FFmpegApiWrap::SwrFree(struct SwrContext **s)
406 {
407     if (swrFreeFunc) {
408         swrFreeFunc(s);
409     }
410 }
411 
SwrConvert(struct SwrContext * s,uint8_t ** out,int outCount,const uint8_t ** in,int inCount)412 int FFmpegApiWrap::SwrConvert(struct SwrContext *s,
413     uint8_t **out, int outCount, const uint8_t **in, int inCount)
414 {
415     int ret = -1;
416     if (swrConvertFunc != nullptr) {
417         ret = swrConvertFunc(s, out, outCount, in, inCount);
418     }
419     return ret;
420 }
421 } // namespace MediaMonitor
422 } // namespace Media
423 } // namespace OHOS