LCOV - code coverage report
Current view: top level - media/server/gstplayer/source - CapsBuilder.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 94.7 % 131 124
Test Date: 2026-03-31 12:03:04 Functions: 100.0 % 19 19

            Line data    Source code
       1              : /*
       2              :  * If not stated otherwise in this file or this component's LICENSE file the
       3              :  * following copyright and licenses apply:
       4              :  *
       5              :  * Copyright 2024 Sky UK
       6              :  *
       7              :  * Licensed under the Apache License, Version 2.0 (the "License");
       8              :  * you may not use this file except in compliance with the License.
       9              :  * You may obtain a copy of the License at
      10              :  *
      11              :  * http://www.apache.org/licenses/LICENSE-2.0
      12              :  *
      13              :  * Unless required by applicable law or agreed to in writing, software
      14              :  * distributed under the License is distributed on an "AS IS" BASIS,
      15              :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16              :  * See the License for the specific language governing permissions and
      17              :  * limitations under the License.
      18              :  */
      19              : 
      20              : #include "CapsBuilder.h"
      21              : #include "GstMimeMapping.h"
      22              : #include "RialtoServerLogging.h"
      23              : #include "TypeConverters.h"
      24              : 
      25              : namespace firebolt::rialto::server
      26              : {
      27           20 : MediaSourceCapsBuilder::MediaSourceCapsBuilder(const std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> &gstWrapper,
      28              :                                                const std::shared_ptr<firebolt::rialto::wrappers::IGlibWrapper> &glibWrapper,
      29           20 :                                                const firebolt::rialto::IMediaPipeline::MediaSourceAV &source)
      30           20 :     : m_gstWrapper(gstWrapper), m_glibWrapper(glibWrapper), m_attachedSource(source)
      31              : {
      32              : }
      33           19 : GstCaps *MediaSourceCapsBuilder::buildCaps()
      34              : {
      35           19 :     return buildCommonCaps();
      36              : }
      37              : 
      38           19 : GstCaps *MediaSourceCapsBuilder::buildCommonCaps()
      39              : {
      40           19 :     GstCaps *caps = firebolt::rialto::server::createSimpleCapsFromMimeType(m_gstWrapper, m_attachedSource);
      41              : 
      42           19 :     addAlignmentToCaps(caps);
      43           19 :     addCodecDataToCaps(caps);
      44           19 :     addStreamFormatToCaps(caps);
      45              : 
      46           19 :     return caps;
      47              : }
      48              : 
      49           19 : void MediaSourceCapsBuilder::addAlignmentToCaps(GstCaps *caps) const
      50              : {
      51              :     static const std::unordered_map<firebolt::rialto::SegmentAlignment, std::string> aligmentMap =
      52           23 :         {{firebolt::rialto::SegmentAlignment::AU, "au"}, {firebolt::rialto::SegmentAlignment::NAL, "nal"}};
      53              : 
      54           19 :     auto aligmentMapIt = aligmentMap.find(m_attachedSource.getSegmentAlignment());
      55           19 :     if (aligmentMapIt != aligmentMap.end())
      56              :     {
      57            7 :         m_gstWrapper->gstCapsSetSimple(caps, "alignment", G_TYPE_STRING, aligmentMapIt->second.c_str(), nullptr);
      58              :     }
      59           20 : }
      60              : 
      61           19 : void MediaSourceCapsBuilder::addCodecDataToCaps(GstCaps *caps) const
      62              : {
      63           19 :     const std::shared_ptr<CodecData> &kCodecData = m_attachedSource.getCodecData();
      64           19 :     if (kCodecData && CodecDataType::BUFFER == kCodecData->type)
      65              :     {
      66            6 :         gpointer memory = m_glibWrapper->gMemdup(kCodecData->data.data(), kCodecData->data.size());
      67            6 :         GstBuffer *buf = m_gstWrapper->gstBufferNewWrapped(memory, kCodecData->data.size());
      68            6 :         m_gstWrapper->gstCapsSetSimple(caps, "codec_data", GST_TYPE_BUFFER, buf, nullptr);
      69            6 :         m_gstWrapper->gstBufferUnref(buf);
      70              :     }
      71           13 :     else if (kCodecData && CodecDataType::STRING == kCodecData->type)
      72              :     {
      73            2 :         std::string codecDataStr{kCodecData->data.begin(), kCodecData->data.end()};
      74            1 :         m_gstWrapper->gstCapsSetSimple(caps, "codec_data", G_TYPE_STRING, codecDataStr.c_str(), nullptr);
      75              :     }
      76           19 : }
      77              : 
      78           19 : void MediaSourceCapsBuilder::addStreamFormatToCaps(GstCaps *caps) const
      79              : {
      80              :     static const std::unordered_map<firebolt::rialto::StreamFormat, std::string> formatMap =
      81            0 :         {{firebolt::rialto::StreamFormat::RAW, "raw"},
      82            0 :          {firebolt::rialto::StreamFormat::AVC, "avc"},
      83            0 :          {firebolt::rialto::StreamFormat::BYTE_STREAM, "byte-stream"},
      84            0 :          {firebolt::rialto::StreamFormat::HVC1, "hvc1"},
      85           26 :          {firebolt::rialto::StreamFormat::HEV1, "hev1"}};
      86              : 
      87           19 :     auto formatMapIt = formatMap.find(m_attachedSource.getStreamFormat());
      88           19 :     if (formatMapIt != formatMap.end())
      89              :     {
      90            7 :         m_gstWrapper->gstCapsSetSimple(caps, "stream-format", G_TYPE_STRING, formatMapIt->second.c_str(), nullptr);
      91              :     }
      92           20 : }
      93              : 
      94           13 : MediaSourceAudioCapsBuilder::MediaSourceAudioCapsBuilder(
      95              :     const std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> &gstWrapper,
      96              :     const std::shared_ptr<firebolt::rialto::wrappers::IGlibWrapper> &glibWrapper,
      97           13 :     const IMediaPipeline::MediaSourceAudio &source)
      98           13 :     : MediaSourceCapsBuilder(gstWrapper, glibWrapper, source), m_attachedAudioSource(source)
      99              : {
     100              : }
     101              : 
     102           13 : GstCaps *MediaSourceAudioCapsBuilder::buildCaps()
     103              : {
     104           13 :     std::string mimeType = m_attachedSource.getMimeType();
     105           13 :     if (mimeType == "audio/x-opus")
     106              :     {
     107            1 :         return createOpusCaps();
     108              :     }
     109              : 
     110           12 :     GstCaps *caps = MediaSourceCapsBuilder::buildCaps();
     111           12 :     if (mimeType == "audio/mp4" || mimeType == "audio/aac")
     112              :     {
     113            5 :         addMpegVersion4ToCaps(caps);
     114              :     }
     115            7 :     else if (mimeType == "audio/mp3")
     116              :     {
     117            1 :         addMp3Caps(caps);
     118              :     }
     119            6 :     else if (mimeType == "audio/b-wav" || mimeType == "audio/x-raw")
     120              :     {
     121            3 :         addRawAudioData(caps);
     122              :     }
     123            3 :     else if (mimeType == "audio/x-flac")
     124              :     {
     125            1 :         addFlacSpecificData(caps);
     126              :     }
     127           12 :     addSampleRateAndChannelsToCaps(caps);
     128              : 
     129           12 :     return caps;
     130           13 : }
     131              : 
     132            1 : GstCaps *MediaSourceAudioCapsBuilder::createOpusCaps()
     133              : {
     134            1 :     GstCaps *caps = getAudioSpecificConfiguration();
     135            1 :     if (!caps)
     136              :     {
     137            0 :         caps = m_gstWrapper->gstCapsNewSimple("audio/x-opus", "channel-mapping-family", G_TYPE_INT, 0, nullptr);
     138            0 :         addSampleRateAndChannelsToCaps(caps);
     139              :     }
     140              : 
     141            1 :     return caps;
     142              : }
     143              : 
     144            1 : GstCaps *MediaSourceAudioCapsBuilder::getAudioSpecificConfiguration() const
     145              : {
     146            1 :     GstCaps *caps = nullptr;
     147            1 :     firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig();
     148            1 :     if (audioConfig.codecSpecificConfig.size())
     149              :     {
     150            1 :         gsize codec_priv_size = audioConfig.codecSpecificConfig.size();
     151            1 :         gconstpointer codec_priv = audioConfig.codecSpecificConfig.data();
     152              : 
     153            1 :         caps = m_gstWrapper->gstCodecUtilsOpusCreateCapsFromHeader(codec_priv, codec_priv_size);
     154            1 :         if (!caps)
     155              :         {
     156            0 :             RIALTO_SERVER_LOG_ERROR("Failed to parse opus header");
     157              :         }
     158              :     }
     159              : 
     160            1 :     return caps;
     161              : }
     162              : 
     163           12 : void MediaSourceAudioCapsBuilder::addSampleRateAndChannelsToCaps(GstCaps *caps) const
     164              : {
     165           12 :     firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig();
     166              : 
     167           12 :     if (audioConfig.numberOfChannels != firebolt::rialto::kInvalidAudioChannels)
     168            4 :         m_gstWrapper->gstCapsSetSimple(caps, "channels", G_TYPE_INT, audioConfig.numberOfChannels, nullptr);
     169              : 
     170           12 :     if (audioConfig.sampleRate != firebolt::rialto::kInvalidAudioSampleRate)
     171            4 :         m_gstWrapper->gstCapsSetSimple(caps, "rate", G_TYPE_INT, audioConfig.sampleRate, nullptr);
     172           12 : }
     173              : 
     174            5 : void MediaSourceAudioCapsBuilder::addMpegVersion4ToCaps(GstCaps *caps) const
     175              : {
     176            5 :     m_gstWrapper->gstCapsSetSimple(caps, "mpegversion", G_TYPE_INT, 4, nullptr);
     177              : }
     178              : 
     179            1 : void MediaSourceAudioCapsBuilder::addMp3Caps(GstCaps *caps) const
     180              : {
     181            1 :     m_gstWrapper->gstCapsSetSimple(caps, "mpegversion", G_TYPE_INT, 1, nullptr);
     182            1 :     m_gstWrapper->gstCapsSetSimple(caps, "layer", G_TYPE_INT, 3, nullptr);
     183              : }
     184              : 
     185            3 : void MediaSourceAudioCapsBuilder::addRawAudioData(GstCaps *caps) const
     186              : {
     187            3 :     firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig();
     188            3 :     if (audioConfig.format.has_value())
     189            2 :         m_gstWrapper->gstCapsSetSimple(caps, "format", G_TYPE_STRING, common::convertFormat(audioConfig.format.value()),
     190              :                                        nullptr);
     191            3 :     if (audioConfig.layout.has_value())
     192            2 :         m_gstWrapper->gstCapsSetSimple(caps, "layout", G_TYPE_STRING, common::convertLayout(audioConfig.layout.value()),
     193              :                                        nullptr);
     194            3 :     if (audioConfig.channelMask.has_value())
     195            2 :         m_gstWrapper->gstCapsSetSimple(caps, "channel-mask", GST_TYPE_BITMASK, audioConfig.channelMask.value(), nullptr);
     196            3 : }
     197              : 
     198            1 : void MediaSourceAudioCapsBuilder::addFlacSpecificData(GstCaps *caps) const
     199              : {
     200            1 :     firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig();
     201            1 :     if (audioConfig.streamHeader.size())
     202              :     {
     203            1 :         GValue streamHeaderArray = G_VALUE_INIT;
     204            1 :         m_glibWrapper->gValueInit(&streamHeaderArray, GST_TYPE_ARRAY);
     205            2 :         for (const auto &header : audioConfig.streamHeader)
     206              :         {
     207            1 :             gpointer memory = m_glibWrapper->gMemdup(header.data(), header.size());
     208            1 :             GstBuffer *buf = m_gstWrapper->gstBufferNewWrapped(memory, header.size());
     209            1 :             GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLAG_HEADER);
     210              : 
     211            1 :             GValue value = G_VALUE_INIT;
     212            1 :             m_glibWrapper->gValueInit(&value, GST_TYPE_BUFFER);
     213            1 :             m_gstWrapper->gstValueSetBuffer(&value, buf);
     214            1 :             m_gstWrapper->gstValueArrayAppendValue(&streamHeaderArray, &value);
     215              : 
     216            1 :             m_glibWrapper->gValueUnset(&value);
     217            1 :             m_gstWrapper->gstBufferUnref(buf);
     218              :         }
     219            1 :         m_gstWrapper->gstStructureSetValue(m_gstWrapper->gstCapsGetStructure(caps, 0), "streamheader",
     220              :                                            &streamHeaderArray);
     221            1 :         m_glibWrapper->gValueUnset(&streamHeaderArray);
     222              :     }
     223            1 :     if (audioConfig.framed.has_value())
     224              :     {
     225            1 :         m_gstWrapper->gstCapsSetSimple(caps, "framed", G_TYPE_BOOLEAN, audioConfig.framed.value(), nullptr);
     226              :     }
     227              : }
     228              : 
     229            7 : MediaSourceVideoCapsBuilder::MediaSourceVideoCapsBuilder(
     230              :     const std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> &gstWrapper,
     231              :     const std::shared_ptr<firebolt::rialto::wrappers::IGlibWrapper> &glibWrapper,
     232            7 :     const IMediaPipeline::MediaSourceVideo &source)
     233            7 :     : MediaSourceCapsBuilder(gstWrapper, glibWrapper, source), m_attachedVideoSource(source)
     234              : {
     235              : }
     236              : 
     237            7 : GstCaps *MediaSourceVideoCapsBuilder::buildCaps()
     238              : {
     239            7 :     GstCaps *caps = MediaSourceCapsBuilder::buildCaps();
     240            7 :     if (m_attachedVideoSource.getWidth() != firebolt::rialto::kUndefinedSize)
     241            6 :         m_gstWrapper->gstCapsSetSimple(caps, "width", G_TYPE_INT, m_attachedVideoSource.getWidth(), nullptr);
     242            7 :     if (m_attachedVideoSource.getHeight() != firebolt::rialto::kUndefinedSize)
     243            6 :         m_gstWrapper->gstCapsSetSimple(caps, "height", G_TYPE_INT, m_attachedVideoSource.getHeight(), nullptr);
     244              : 
     245            7 :     return caps;
     246              : }
     247              : 
     248            1 : MediaSourceVideoDolbyVisionCapsBuilder::MediaSourceVideoDolbyVisionCapsBuilder(
     249              :     const std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> &gstWrapper,
     250              :     const std::shared_ptr<firebolt::rialto::wrappers::IGlibWrapper> &glibWrapper,
     251            1 :     const IMediaPipeline::MediaSourceVideoDolbyVision &source)
     252            1 :     : MediaSourceVideoCapsBuilder(gstWrapper, glibWrapper, source), m_attachedDolbySource(source)
     253              : {
     254              : }
     255              : 
     256            1 : GstCaps *MediaSourceVideoDolbyVisionCapsBuilder::buildCaps()
     257              : {
     258            1 :     GstCaps *caps = MediaSourceVideoCapsBuilder::buildCaps();
     259            1 :     m_gstWrapper->gstCapsSetSimple(caps, "dovi-stream", G_TYPE_BOOLEAN, true, nullptr);
     260            1 :     m_gstWrapper->gstCapsSetSimple(caps, "dv_profile", G_TYPE_UINT, m_attachedDolbySource.getDolbyVisionProfile(),
     261              :                                    nullptr);
     262            1 :     return caps;
     263              : }
     264              : } // namespace firebolt::rialto::server
        

Generated by: LCOV version 2.0-1