|  | // Copyright 2018 The Cobalt Authors. All Rights Reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | // This file implements the FFMPEGDispatch interface for a library linked | 
|  | // directly, or which the symbols are already available in the global namespace. | 
|  |  | 
|  | #include "starboard/shared/ffmpeg/ffmpeg_dispatch.h" | 
|  |  | 
|  | #include <dlfcn.h> | 
|  | #include <map> | 
|  |  | 
|  | #include "starboard/common/log.h" | 
|  | #include "starboard/common/scoped_ptr.h" | 
|  | #include "starboard/common/string.h" | 
|  | #include "starboard/once.h" | 
|  | #include "starboard/shared/ffmpeg/ffmpeg_common.h" | 
|  | #include "starboard/shared/starboard/lazy_initialization_internal.h" | 
|  |  | 
|  | namespace starboard { | 
|  | namespace shared { | 
|  | namespace ffmpeg { | 
|  | namespace { | 
|  |  | 
|  | FFMPEGDispatch* g_ffmpeg_dispatch_impl; | 
|  | SbOnceControl g_construct_ffmpeg_dispatch_once = SB_ONCE_INITIALIZER; | 
|  |  | 
|  | void construct_ffmpeg_dispatch() { | 
|  | g_ffmpeg_dispatch_impl = new FFMPEGDispatch(); | 
|  | } | 
|  |  | 
|  | void LoadSymbols(FFMPEGDispatch* ffmpeg) { | 
|  | SB_DCHECK(ffmpeg->is_valid()); | 
|  | // Load the desired symbols from the shared libraries. Note: If a symbol is | 
|  | // listed as a '.text' entry in the output of 'objdump -T' on the shared | 
|  | // library file, then it is directly available from it. | 
|  |  | 
|  | #define INITSYMBOL(symbol) \ | 
|  | ffmpeg->symbol = reinterpret_cast<decltype(FFMPEGDispatch::symbol)>(symbol); | 
|  |  | 
|  | // Load symbols from the avutil shared library. | 
|  | INITSYMBOL(avutil_version); | 
|  | SB_DCHECK(ffmpeg->avutil_version); | 
|  | INITSYMBOL(av_malloc); | 
|  | INITSYMBOL(av_freep); | 
|  | #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 8, 0) | 
|  | INITSYMBOL(av_frame_alloc); | 
|  | INITSYMBOL(av_frame_unref); | 
|  | #endif | 
|  | INITSYMBOL(av_samples_get_buffer_size); | 
|  | INITSYMBOL(av_opt_set_int); | 
|  | INITSYMBOL(av_image_check_size); | 
|  | INITSYMBOL(av_buffer_create); | 
|  |  | 
|  | // Load symbols from the avcodec shared library. | 
|  | INITSYMBOL(avcodec_version); | 
|  | SB_DCHECK(ffmpeg->avcodec_version); | 
|  | INITSYMBOL(avcodec_alloc_context3); | 
|  | INITSYMBOL(avcodec_find_decoder); | 
|  | INITSYMBOL(avcodec_close); | 
|  | INITSYMBOL(avcodec_open2); | 
|  | INITSYMBOL(av_init_packet); | 
|  | INITSYMBOL(avcodec_decode_audio4); | 
|  | INITSYMBOL(avcodec_decode_video2); | 
|  | INITSYMBOL(avcodec_flush_buffers); | 
|  | #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 8, 0) | 
|  | INITSYMBOL(avcodec_alloc_frame); | 
|  | INITSYMBOL(avcodec_get_frame_defaults); | 
|  | #endif | 
|  | INITSYMBOL(avcodec_align_dimensions2); | 
|  |  | 
|  | // Load symbols from the avformat shared library. | 
|  | INITSYMBOL(avformat_version); | 
|  | SB_DCHECK(ffmpeg->avformat_version); | 
|  | INITSYMBOL(av_register_all); | 
|  | SB_DCHECK(ffmpeg->av_register_all); | 
|  |  | 
|  | #undef INITSYMBOL | 
|  | } | 
|  | }  // namespace | 
|  |  | 
|  | FFMPEGDispatch::FFMPEGDispatch() { | 
|  | LoadSymbols(this); | 
|  | av_register_all(); | 
|  | } | 
|  |  | 
|  | FFMPEGDispatch::~FFMPEGDispatch() {} | 
|  |  | 
|  | // static | 
|  | FFMPEGDispatch* FFMPEGDispatch::GetInstance() { | 
|  | bool initialized = | 
|  | SbOnce(&g_construct_ffmpeg_dispatch_once, construct_ffmpeg_dispatch); | 
|  | SB_DCHECK(initialized); | 
|  | return g_ffmpeg_dispatch_impl; | 
|  | } | 
|  |  | 
|  | // static | 
|  | bool FFMPEGDispatch::RegisterSpecialization(int specialization, | 
|  | int avcodec, | 
|  | int avformat, | 
|  | int avutil) { | 
|  | // There is always only a single version of the library linked to the | 
|  | // application, so there is no need to explicitly track multiple versions. | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool FFMPEGDispatch::is_valid() const { | 
|  | // Loading of a linked library is always successful. | 
|  | return true; | 
|  | } | 
|  |  | 
|  | int FFMPEGDispatch::specialization_version() const { | 
|  | // There is only one version of ffmpeg linked to the binary. | 
|  | return FFMPEG; | 
|  | } | 
|  |  | 
|  | }  // namespace ffmpeg | 
|  | }  // namespace shared | 
|  | }  // namespace starboard |