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 2022 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 "tasks/generic/ReadShmDataAndAttachSamples.h"
21 : #include "GenericPlayerContext.h"
22 : #include "IDataReader.h"
23 : #include "IGstGenericPlayerPrivate.h"
24 : #include "IMediaPipeline.h"
25 : #include "RialtoServerLogging.h"
26 : #include "TypeConverters.h"
27 :
28 : namespace
29 : {
30 : constexpr auto kDelayThreshold{5 * GST_SECOND};
31 : } // namespace
32 :
33 : namespace firebolt::rialto::server::tasks::generic
34 : {
35 7 : ReadShmDataAndAttachSamples::ReadShmDataAndAttachSamples(
36 : GenericPlayerContext &context, const std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> &gstWrapper,
37 7 : IGstGenericPlayerPrivate &player, const std::shared_ptr<IDataReader> &dataReader)
38 7 : : m_context{context}, m_gstWrapper{gstWrapper}, m_player{player}, m_dataReader{dataReader}
39 : {
40 7 : RIALTO_SERVER_LOG_DEBUG("Constructing ReadShmDataAndAttachSamples");
41 : }
42 :
43 8 : ReadShmDataAndAttachSamples::~ReadShmDataAndAttachSamples()
44 : {
45 7 : RIALTO_SERVER_LOG_DEBUG("ReadShmDataAndAttachSamples finished");
46 8 : }
47 :
48 6 : void ReadShmDataAndAttachSamples::execute() const
49 : {
50 6 : RIALTO_SERVER_LOG_DEBUG("Executing ReadShmDataAndAttachSamples");
51 : // Read media segments from shared memory
52 6 : IMediaPipeline::MediaSegmentVector mediaSegments = m_dataReader->readData();
53 :
54 18 : for (const auto &mediaSegment : mediaSegments)
55 : {
56 12 : if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::UNKNOWN)
57 : {
58 2 : RIALTO_SERVER_LOG_WARN("Unknown media segment type");
59 2 : continue;
60 : }
61 :
62 10 : GstBuffer *gstBuffer = m_player.createBuffer(*mediaSegment);
63 10 : if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::VIDEO)
64 : {
65 : try
66 : {
67 : IMediaPipeline::MediaSegmentVideo &videoSegment =
68 2 : dynamic_cast<IMediaPipeline::MediaSegmentVideo &>(*mediaSegment);
69 2 : m_player.updateVideoCaps(videoSegment.getWidth(), videoSegment.getHeight(), videoSegment.getFrameRate(),
70 : videoSegment.getCodecData());
71 : }
72 0 : catch (const std::exception &e)
73 : {
74 0 : RIALTO_SERVER_LOG_ERROR("Failed to get the video segment, reason: %s", e.what());
75 : }
76 : }
77 8 : else if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::AUDIO)
78 : {
79 : try
80 : {
81 : IMediaPipeline::MediaSegmentAudio &audioSegment =
82 4 : dynamic_cast<IMediaPipeline::MediaSegmentAudio &>(*mediaSegment);
83 4 : m_player.updateAudioCaps(audioSegment.getSampleRate(), audioSegment.getNumberOfChannels(),
84 : audioSegment.getCodecData());
85 4 : m_player.addAudioClippingToBuffer(gstBuffer, audioSegment.getClippingStart(),
86 : audioSegment.getClippingEnd());
87 : }
88 0 : catch (const std::exception &e)
89 : {
90 0 : RIALTO_SERVER_LOG_ERROR("Failed to get the audio segment, reason: %s", e.what());
91 : }
92 : }
93 4 : else if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::SUBTITLE)
94 : {
95 4 : if (mediaSegment->getDisplayOffset())
96 : {
97 4 : GST_BUFFER_OFFSET(gstBuffer) = mediaSegment->getDisplayOffset().value();
98 : }
99 : }
100 :
101 10 : attachData(mediaSegment->getType(), gstBuffer);
102 : }
103 : // All segments in vector have the same type
104 6 : if (!mediaSegments.empty())
105 : {
106 6 : const auto kMediaType{mediaSegments.front()->getType()};
107 6 : const auto kFirstTimestamp{mediaSegments.front()->getTimeStamp()};
108 6 : const auto kLastTimestamp{mediaSegments.back()->getTimeStamp()};
109 6 : RIALTO_SERVER_LOG_DEBUG("%s data received. First ts: %" GST_TIME_FORMAT " last ts: %" GST_TIME_FORMAT,
110 : common::convertMediaSourceType(kMediaType), GST_TIME_ARGS(kFirstTimestamp),
111 : GST_TIME_ARGS(kLastTimestamp));
112 8 : if (!m_dataReader->isBufferFull() && m_context.streamPosition.load() != -1 &&
113 2 : kLastTimestamp >= m_context.streamPosition.load() + kDelayThreshold)
114 : {
115 9 : RIALTO_SERVER_LOG_DEBUG("Received %zu segments, current pos: %" GST_TIME_FORMAT
116 : " last received ts: %" GST_TIME_FORMAT ", scheduling NeedMediaData with delay",
117 : mediaSegments.size(), GST_TIME_ARGS(m_context.streamPosition.load()),
118 : GST_TIME_ARGS(kLastTimestamp));
119 1 : m_player.notifyNeedMediaDataWithDelay(kMediaType);
120 1 : return;
121 : }
122 5 : m_player.notifyNeedMediaData(kMediaType);
123 : }
124 6 : }
125 :
126 10 : void ReadShmDataAndAttachSamples::attachData(const firebolt::rialto::MediaSourceType mediaType, GstBuffer *buffer) const
127 : {
128 10 : auto elem = m_context.streamInfo.find(mediaType);
129 10 : if (elem != m_context.streamInfo.end())
130 : {
131 8 : elem->second.buffers.push_back(buffer);
132 8 : m_player.attachData(mediaType);
133 : }
134 : else
135 : {
136 2 : RIALTO_SERVER_LOG_WARN("Could not find stream info for %s", common::convertMediaSourceType(mediaType));
137 2 : m_gstWrapper->gstBufferUnref(buffer);
138 : }
139 10 : }
140 : } // namespace firebolt::rialto::server::tasks::generic
|