Skip to content

Commit 0a7a589

Browse files
Send segment twice to be sure, that it will be replaced by GstAppSrc (rdkcentral#365)
Summary: Send segment twice to be sure, that it will be replaced by GstAppSrc Type: Fix Test Plan: Fullstack, UT Jira: RDKAAMP-3975
1 parent 5babeef commit 0a7a589

4 files changed

Lines changed: 97 additions & 0 deletions

File tree

media/server/gstplayer/include/GenericPlayerContext.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,13 @@ struct GenericPlayerContext
230230
*/
231231
std::map<GstElement *, std::vector<SegmentData>> initialPositions;
232232

233+
/**
234+
* @brief Currently set position of a source. Used to check, if additional segment should be pushed.
235+
*
236+
* Attribute can be used only in worker thread
237+
*/
238+
std::map<GstElement *, SegmentData> currentPosition;
239+
233240
/**
234241
* @brief The mutex, which protects properties, which are read/written by main/worker thread.
235242
* This mutex should be removed in future, when we find out better solution for

media/server/gstplayer/include/GstGenericPlayer.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,15 @@ class GstGenericPlayer : public IGstGenericPlayer, public IGstGenericPlayerPriva
316316
*/
317317
void setTextTrackPositionIfRequired(GstElement *source);
318318

319+
/**
320+
* @brief GstAppSrc does not replace segment, if it's the same as previous one.
321+
* It causes problems with position reporing in amlogic devices, so we need to push
322+
* two segments with different reset time value.
323+
*
324+
* @param[in] source : the media source
325+
*/
326+
void pushAdditionalSegmentIfRequired(GstElement *source);
327+
319328
private:
320329
/**
321330
* @brief The player context.

media/server/gstplayer/source/GstGenericPlayer.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ namespace
4141
* whenever the session moves to another playback state.
4242
*/
4343
constexpr std::chrono::milliseconds kPositionReportTimerMs{250};
44+
45+
bool operator==(const firebolt::rialto::server::SegmentData &lhs, const firebolt::rialto::server::SegmentData &rhs)
46+
{
47+
return (lhs.position == rhs.position) && (lhs.resetTime == rhs.resetTime) && (lhs.appliedRate == rhs.appliedRate) &&
48+
(lhs.stopPosition == rhs.stopPosition);
49+
}
4450
} // namespace
4551

4652
namespace firebolt::rialto::server
@@ -926,6 +932,11 @@ void GstGenericPlayer::pushSampleIfRequired(GstElement *source, const std::strin
926932
// Sending initial sample not needed
927933
return;
928934
}
935+
// GstAppSrc does not replace segment, if it's the same as previous one.
936+
// It causes problems with position reporing in amlogic devices, so we need to push
937+
// two segments with different reset time value.
938+
pushAdditionalSegmentIfRequired(source);
939+
929940
for (const auto &[position, resetTime, appliedRate, stopPosition] : initialPosition->second)
930941
{
931942
GstSeekFlags seekFlag = resetTime ? GST_SEEK_FLAG_FLUSH : GST_SEEK_FLAG_NONE;
@@ -957,10 +968,33 @@ void GstGenericPlayer::pushSampleIfRequired(GstElement *source, const std::strin
957968

958969
m_gstWrapper->gstSegmentFree(segment);
959970
}
971+
m_context.currentPosition[source] = initialPosition->second.back();
960972
m_context.initialPositions.erase(initialPosition);
961973
return;
962974
}
963975

976+
void GstGenericPlayer::pushAdditionalSegmentIfRequired(GstElement *source)
977+
{
978+
auto currentPosition = m_context.currentPosition.find(source);
979+
if (m_context.currentPosition.end() == currentPosition)
980+
{
981+
return;
982+
}
983+
auto initialPosition = m_context.initialPositions.find(source);
984+
if (m_context.initialPositions.end() == initialPosition)
985+
{
986+
return;
987+
}
988+
if (initialPosition->second.size() == 1 && initialPosition->second.back().resetTime &&
989+
currentPosition->second == initialPosition->second.back())
990+
{
991+
RIALTO_SERVER_LOG_INFO("Adding additional segment with reset_time = false");
992+
SegmentData additionalSegment = initialPosition->second.back();
993+
additionalSegment.resetTime = false;
994+
initialPosition->second.push_back(additionalSegment);
995+
}
996+
}
997+
964998
void GstGenericPlayer::setTextTrackPositionIfRequired(GstElement *source)
965999
{
9661000
auto initialPosition = m_context.initialPositions.find(source);

tests/unittests/media/server/gstplayer/genericPlayer/GstGenericPlayerPrivateTest.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,53 @@ TEST_F(GstGenericPlayerPrivateTest, shouldAttachAudioSample)
904904
EXPECT_EQ(segment.applied_rate, kAppliedRate);
905905
}
906906

907+
TEST_F(GstGenericPlayerPrivateTest, shouldAttachAdditionalAudioSample)
908+
{
909+
constexpr std::int64_t kPosition{124};
910+
constexpr double kRate{1.0};
911+
constexpr bool kResetTime{true};
912+
constexpr double kAppliedRate{1.0};
913+
constexpr uint64_t kStopPosition{3453425};
914+
GstBuffer buffer{};
915+
GstAppSrc audioSrc{};
916+
GstAppSrc videoSrc{};
917+
GstSegment segment{};
918+
GstSample *sample{nullptr};
919+
GstCaps caps{};
920+
modifyContext(
921+
[&](GenericPlayerContext &context)
922+
{
923+
context.streamInfo[firebolt::rialto::MediaSourceType::AUDIO].buffers.emplace_back(&buffer);
924+
context.streamInfo[firebolt::rialto::MediaSourceType::AUDIO].isDataNeeded = true;
925+
context.playbackRate = kRate;
926+
context.streamInfo[firebolt::rialto::MediaSourceType::AUDIO].appSrc = GST_ELEMENT(&audioSrc);
927+
context.initialPositions[GST_ELEMENT(&audioSrc)].emplace_back(
928+
SegmentData{kPosition, kResetTime, kAppliedRate, kStopPosition});
929+
context.streamInfo[firebolt::rialto::MediaSourceType::VIDEO].appSrc = GST_ELEMENT(&videoSrc);
930+
context.currentPosition[GST_ELEMENT(&audioSrc)] =
931+
SegmentData{kPosition, kResetTime, kAppliedRate, kStopPosition};
932+
});
933+
EXPECT_CALL(*m_gstWrapperMock, gstAppSrcGetCaps(&audioSrc)).WillRepeatedly(Return(&caps));
934+
EXPECT_CALL(*m_gstWrapperMock, gstSegmentNew()).WillRepeatedly(Return(&segment));
935+
EXPECT_CALL(*m_gstWrapperMock, gstSegmentInit(&segment, GST_FORMAT_TIME)).Times(2);
936+
EXPECT_CALL(*m_gstWrapperMock,
937+
gstSegmentDoSeek(&segment, kRate, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, kPosition,
938+
GST_SEEK_TYPE_SET, kStopPosition, nullptr))
939+
.WillOnce(Return(true));
940+
EXPECT_CALL(*m_gstWrapperMock,
941+
gstSegmentDoSeek(&segment, kRate, GST_FORMAT_TIME, GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_SET, kPosition,
942+
GST_SEEK_TYPE_SET, kStopPosition, nullptr))
943+
.WillOnce(Return(true));
944+
EXPECT_CALL(*m_gstWrapperMock, gstSampleNew(nullptr, &caps, &segment, nullptr)).WillRepeatedly(Return(sample));
945+
EXPECT_CALL(*m_gstWrapperMock, gstAppSrcPushSample(&audioSrc, sample)).Times(2);
946+
EXPECT_CALL(*m_gstWrapperMock, gstSampleUnref(sample)).Times(2);
947+
EXPECT_CALL(*m_gstWrapperMock, gstSegmentFree(&segment)).Times(2);
948+
EXPECT_CALL(*m_gstWrapperMock, gstCapsUnref(&caps)).Times(2);
949+
EXPECT_CALL(*m_gstWrapperMock, gstAppSrcPushBuffer(_, &buffer));
950+
m_sut->attachData(firebolt::rialto::MediaSourceType::AUDIO);
951+
EXPECT_EQ(segment.applied_rate, kAppliedRate);
952+
}
953+
907954
TEST_F(GstGenericPlayerPrivateTest, undefinedStopPositionInSetSourcePosition)
908955
{
909956
constexpr std::int64_t kPosition{124};

0 commit comments

Comments
 (0)