LCOV - code coverage report
Current view: top level - muse/framework/media/internal/ffmpeg/v8 - ffmpeglibhandler.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 147 0
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2025 MuseScore Limited
       9              :  *
      10              :  * This program is free software; you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program; if not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #include "ffmpeglibhandler.h"
      24              : 
      25              : #include "io/fileinfo.h"
      26              : #include "global/dlib.h"
      27              : 
      28              : #include "log.h"
      29              : 
      30              : namespace muse::media::ffmpeg::v8 {
      31              : #define RESOLVE_FROM(lib, name) do { \
      32              :         name = reinterpret_cast<decltype(name)>(getSymbol(lib, #name)); \
      33              :         if (!name) { LOGW() << "FFmpeg: missing symbol " #name; clearFunctions(); return false; } \
      34              : } while (0)
      35              : 
      36            0 : FFmpegLibHandler::~FFmpegLibHandler()
      37              : {
      38            0 :     unload();
      39            0 : }
      40              : 
      41            0 : void* FFmpegLibHandler::getSymbol(void* lib, const char* name) const
      42              : {
      43            0 :     if (!lib) {
      44            0 :         return nullptr;
      45              :     }
      46            0 :     return muse::getLibFunc(lib, name);
      47              : }
      48              : 
      49            0 : bool FFmpegLibHandler::loadApi()
      50              : {
      51            0 :     if (!m_avUtilLibrary || !m_avCodecLibrary || !m_avFormatLibrary || !m_swsScaleLibrary || !m_swResampleLibrary) {
      52            0 :         return false;
      53              :     }
      54              : 
      55            0 :     clearFunctions();
      56              : 
      57              :     // libavutil
      58            0 :     RESOLVE_FROM(m_avUtilLibrary, av_rescale_q);
      59            0 :     RESOLVE_FROM(m_avUtilLibrary, av_image_fill_arrays);
      60            0 :     RESOLVE_FROM(m_avUtilLibrary, av_image_get_buffer_size);
      61            0 :     RESOLVE_FROM(m_avUtilLibrary, av_opt_set_int);
      62            0 :     RESOLVE_FROM(m_avUtilLibrary, av_frame_alloc);
      63            0 :     RESOLVE_FROM(m_avUtilLibrary, av_frame_free);
      64            0 :     RESOLVE_FROM(m_avUtilLibrary, av_malloc);
      65              : 
      66              :     // libavformat
      67            0 :     RESOLVE_FROM(m_avFormatLibrary, av_write_trailer);
      68            0 :     RESOLVE_FROM(m_avFormatLibrary, av_interleaved_write_frame);
      69            0 :     RESOLVE_FROM(m_avFormatLibrary, av_read_frame);
      70            0 :     RESOLVE_FROM(m_avFormatLibrary, avio_open);
      71            0 :     RESOLVE_FROM(m_avFormatLibrary, avio_close);
      72            0 :     RESOLVE_FROM(m_avFormatLibrary, avformat_new_stream);
      73            0 :     RESOLVE_FROM(m_avFormatLibrary, avformat_write_header);
      74            0 :     RESOLVE_FROM(m_avFormatLibrary, avformat_open_input);
      75            0 :     RESOLVE_FROM(m_avFormatLibrary, avformat_find_stream_info);
      76            0 :     RESOLVE_FROM(m_avFormatLibrary, avformat_close_input);
      77            0 :     RESOLVE_FROM(m_avFormatLibrary, avformat_free_context);
      78            0 :     RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_output_context2);
      79            0 :     RESOLVE_FROM(m_avFormatLibrary, avformat_alloc_context);
      80            0 :     RESOLVE_FROM(m_avFormatLibrary, avio_alloc_context);
      81            0 :     RESOLVE_FROM(m_avFormatLibrary, avio_context_free);
      82              : 
      83              :     // libavcodec
      84            0 :     RESOLVE_FROM(m_avCodecLibrary, av_packet_alloc);
      85            0 :     RESOLVE_FROM(m_avCodecLibrary, av_packet_free);
      86            0 :     RESOLVE_FROM(m_avCodecLibrary, av_packet_unref);
      87            0 :     RESOLVE_FROM(m_avCodecLibrary, av_packet_rescale_ts);
      88            0 :     RESOLVE_FROM(m_avCodecLibrary, avcodec_alloc_context3);
      89            0 :     RESOLVE_FROM(m_avCodecLibrary, avcodec_find_encoder);
      90            0 :     RESOLVE_FROM(m_avCodecLibrary, avcodec_find_decoder);
      91            0 :     RESOLVE_FROM(m_avCodecLibrary, avcodec_free_context);
      92            0 :     RESOLVE_FROM(m_avCodecLibrary, avcodec_open2);
      93            0 :     RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_from_context);
      94            0 :     RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_to_context);
      95            0 :     RESOLVE_FROM(m_avCodecLibrary, avcodec_parameters_copy);
      96            0 :     RESOLVE_FROM(m_avCodecLibrary, avcodec_send_frame);
      97            0 :     RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_packet);
      98            0 :     RESOLVE_FROM(m_avCodecLibrary, avcodec_send_packet);
      99            0 :     RESOLVE_FROM(m_avCodecLibrary, avcodec_receive_frame);
     100              : 
     101              :     // libswscale
     102            0 :     RESOLVE_FROM(m_swsScaleLibrary, sws_getCachedContext);
     103            0 :     RESOLVE_FROM(m_swsScaleLibrary, sws_scale);
     104            0 :     RESOLVE_FROM(m_swsScaleLibrary, sws_freeContext);
     105              : 
     106            0 :     return functionsValid();
     107              : }
     108              : 
     109            0 : bool FFmpegLibHandler::loadLib(const io::path_t& avUtilPath, const io::path_t& avCodecPath, const io::path_t& avFormatPath,
     110              :                                const io::path_t& swScalePath, const io::path_t& swResamplePath)
     111              : {
     112            0 :     unload();
     113              : 
     114              :     // Load avutil first, then swresample, swscale, avcodec, avformat (dependency order)
     115            0 :     if (!tryLoadPath(m_avUtilLibrary, avUtilPath)
     116            0 :         || !tryLoadPath(m_swResampleLibrary, swResamplePath)
     117            0 :         || !tryLoadPath(m_swsScaleLibrary, swScalePath)
     118            0 :         || !tryLoadPath(m_avCodecLibrary, avCodecPath)
     119            0 :         || !tryLoadPath(m_avFormatLibrary, avFormatPath)) {
     120            0 :         unload();
     121            0 :         return false;
     122              :     }
     123              : 
     124            0 :     LOGI() << "FFmpeg loaded: avutil=" << avUtilPath << ", avcodec=" << avCodecPath << ", avformat=" << avFormatPath
     125            0 :            << ", swscale=" << swScalePath << ", swresample=" << swResamplePath;
     126              : 
     127            0 :     return true;
     128              : }
     129              : 
     130            0 : void FFmpegLibHandler::unload()
     131              : {
     132            0 :     closeLib(m_avFormatLibrary);
     133            0 :     closeLib(m_swResampleLibrary);
     134            0 :     closeLib(m_swsScaleLibrary);
     135            0 :     closeLib(m_avCodecLibrary);
     136            0 :     closeLib(m_avUtilLibrary);
     137              : 
     138            0 :     clearFunctions();
     139            0 : }
     140              : 
     141            0 : void FFmpegLibHandler::closeLib(void*& lib)
     142              : {
     143            0 :     if (lib) {
     144            0 :         muse::closeLib(lib);
     145            0 :         lib = nullptr;
     146              :     }
     147            0 : }
     148              : 
     149            0 : bool FFmpegLibHandler::tryLoadPath(void*& lib, const io::path_t& fullPath)
     150              : {
     151            0 :     if (!io::FileInfo::exists(fullPath)) {
     152            0 :         return false;
     153              :     }
     154              : 
     155            0 :     void* loaded = muse::loadLib(fullPath);
     156            0 :     if (loaded) {
     157            0 :         lib = loaded;
     158            0 :         return true;
     159              :     }
     160              : 
     161            0 :     return false;
     162              : }
     163              : 
     164            0 : bool FFmpegLibHandler::functionsValid() const
     165              : {
     166            0 :     return av_rescale_q
     167            0 :            && av_image_fill_arrays && av_image_get_buffer_size
     168            0 :            && av_opt_set_int
     169            0 :            && avformat_new_stream
     170            0 :            && avformat_write_header && av_write_trailer
     171            0 :            && avio_open && avio_close && av_interleaved_write_frame
     172            0 :            && avformat_open_input && avformat_find_stream_info
     173            0 :            && avformat_close_input && avformat_free_context
     174            0 :            && avformat_alloc_output_context2 && av_read_frame
     175            0 :            && avformat_alloc_context && avio_alloc_context && avio_context_free
     176            0 :            && avcodec_alloc_context3 && avcodec_find_encoder && avcodec_find_decoder && avcodec_free_context
     177            0 :            && avcodec_open2 && avcodec_parameters_from_context && avcodec_parameters_to_context && avcodec_parameters_copy
     178            0 :            && avcodec_send_frame && avcodec_receive_packet && avcodec_send_packet && avcodec_receive_frame
     179            0 :            && av_frame_alloc && av_frame_free
     180            0 :            && av_packet_alloc && av_packet_free && av_packet_unref && av_packet_rescale_ts
     181            0 :            && av_malloc
     182            0 :            && sws_getCachedContext && sws_scale && sws_freeContext;
     183              : }
     184              : 
     185            0 : void FFmpegLibHandler::clearFunctions()
     186              : {
     187            0 :     av_rescale_q = nullptr;
     188            0 :     av_image_fill_arrays = nullptr;
     189            0 :     av_image_get_buffer_size = nullptr;
     190            0 :     av_opt_set_int = nullptr;
     191            0 :     av_malloc = nullptr;
     192            0 :     avformat_new_stream = nullptr;
     193            0 :     avformat_write_header = nullptr;
     194            0 :     av_write_trailer = nullptr;
     195            0 :     avio_open = nullptr;
     196            0 :     avio_close = nullptr;
     197            0 :     av_interleaved_write_frame = nullptr;
     198            0 :     avformat_open_input = nullptr;
     199            0 :     avformat_find_stream_info = nullptr;
     200            0 :     avformat_close_input = nullptr;
     201            0 :     avformat_free_context = nullptr;
     202            0 :     avformat_alloc_output_context2 = nullptr;
     203            0 :     av_read_frame = nullptr;
     204            0 :     avformat_alloc_context = nullptr;
     205            0 :     avio_alloc_context = nullptr;
     206            0 :     avio_context_free = nullptr;
     207            0 :     avcodec_alloc_context3 = nullptr;
     208            0 :     avcodec_find_encoder = nullptr;
     209            0 :     avcodec_find_decoder = nullptr;
     210            0 :     avcodec_free_context = nullptr;
     211            0 :     avcodec_open2 = nullptr;
     212            0 :     avcodec_parameters_from_context = nullptr;
     213            0 :     avcodec_parameters_to_context = nullptr;
     214            0 :     avcodec_parameters_copy = nullptr;
     215            0 :     avcodec_send_frame = nullptr;
     216            0 :     avcodec_receive_packet = nullptr;
     217            0 :     avcodec_send_packet = nullptr;
     218            0 :     avcodec_receive_frame = nullptr;
     219            0 :     av_frame_alloc = nullptr;
     220            0 :     av_frame_free = nullptr;
     221            0 :     av_packet_alloc = nullptr;
     222            0 :     av_packet_free = nullptr;
     223            0 :     av_packet_unref = nullptr;
     224            0 :     av_packet_rescale_ts = nullptr;
     225            0 :     sws_getCachedContext = nullptr;
     226            0 :     sws_scale = nullptr;
     227            0 :     sws_freeContext = nullptr;
     228            0 : }
     229              : }
        

Generated by: LCOV version 2.0-1