[vlc-commits] [Git][videolan/vlc][master] 3 commits: demux: adaptive: constify method
François Cartegnie (@fcartegnie)
gitlab at videolan.org
Wed Jul 12 08:51:01 UTC 2023
François Cartegnie pushed to branch master at VideoLAN / VLC
Commits:
50af6c7a by Francois Cartegnie at 2023-07-12T08:08:42+00:00
demux: adaptive: constify method
- - - - -
e0a1df00 by Francois Cartegnie at 2023-07-12T08:08:42+00:00
demux: adaptive: add selection state getter
- - - - -
479e9f3f by Francois Cartegnie at 2023-07-12T08:08:42+00:00
test: adaptive: check es reuse and reselection
- - - - -
6 changed files:
- modules/demux/adaptive/plumbing/FakeESOut.cpp
- modules/demux/adaptive/plumbing/FakeESOut.hpp
- modules/demux/adaptive/plumbing/FakeESOutID.cpp
- modules/demux/adaptive/plumbing/FakeESOutID.hpp
- modules/demux/adaptive/test/plumbing/CommandsQueue.cpp
- modules/demux/adaptive/test/plumbing/FakeEsOut.cpp
Changes:
=====================================
modules/demux/adaptive/plumbing/FakeESOut.cpp
=====================================
@@ -283,7 +283,7 @@ void FakeESOut::createOrRecycleRealEsID( AbstractFakeESOutID *es_id_ )
Otherwise the es will select any other compatible track
and will end this in a activate/select loop when reactivating a track */
if( !b_select )
- es_out_Control( real_es_out, ES_OUT_GET_ES_STATE, cand->realESID(), &b_select );
+ b_select = hasSelectedEs( cand );
}
else /* replace format instead of new ES */
{
@@ -435,19 +435,25 @@ void FakeESOut::gc()
bool FakeESOut::hasSelectedEs() const
{
- bool b_selected = false;
std::list<FakeESOutID *> const * lists[2] = {&declared, &fakeesidlist};
std::list<FakeESOutID *>::const_iterator it;
for(int i=0; i<2; i++)
+ for( it=lists[i]->begin(); it!=lists[i]->end(); ++it )
+ if( hasSelectedEs( *it ) )
+ return true;
+ return false;
+}
+
+bool FakeESOut::hasSelectedEs(const AbstractFakeESOutID *id) const
+{
+ if( id->realESID() )
{
- for( it=lists[i]->begin(); it!=lists[i]->end() && !b_selected; ++it )
- {
- FakeESOutID *esID = *it;
- if( esID->realESID() )
- es_out_Control( real_es_out, ES_OUT_GET_ES_STATE, esID->realESID(), &b_selected );
- }
+ bool b_selected;
+ return es_out_Control( real_es_out, ES_OUT_GET_ES_STATE,
+ id->realESID(), &b_selected ) == VLC_SUCCESS
+ && b_selected;
}
- return b_selected;
+ return false;
}
bool FakeESOut::decodersDrained()
=====================================
modules/demux/adaptive/plumbing/FakeESOut.hpp
=====================================
@@ -89,6 +89,7 @@ namespace adaptive
void resetTimestamps();
size_t esCount() const;
bool hasSelectedEs() const;
+ bool hasSelectedEs(const AbstractFakeESOutID *) const;
bool decodersDrained();
bool restarting() const;
void setExtraInfoProvider( ExtraFMTInfoInterface * );
=====================================
modules/demux/adaptive/plumbing/FakeESOutID.cpp
=====================================
@@ -70,7 +70,7 @@ void FakeESOutID::release()
fakeesout->recycle( this );
}
-es_out_id_t * FakeESOutID::realESID()
+es_out_id_t * FakeESOutID::realESID() const
{
return p_real_es_id;
}
=====================================
modules/demux/adaptive/plumbing/FakeESOutID.hpp
=====================================
@@ -38,7 +38,7 @@ namespace adaptive
{
public:
virtual ~AbstractFakeESOutID() = default;
- virtual es_out_id_t * realESID() = 0;
+ virtual es_out_id_t * realESID() const = 0;
virtual void create() = 0;
virtual void release() = 0;
virtual void sendData(block_t *) = 0;
@@ -51,7 +51,7 @@ namespace adaptive
FakeESOutID( FakeESOut *, const es_format_t * );
virtual ~FakeESOutID();
void setRealESID( es_out_id_t * );
- virtual es_out_id_t * realESID() override;
+ virtual es_out_id_t * realESID() const override;
const es_format_t *getFmt() const;
virtual void create() override;
virtual void release() override;
=====================================
modules/demux/adaptive/test/plumbing/CommandsQueue.cpp
=====================================
@@ -75,7 +75,7 @@ class TestEsOutID : public AbstractFakeESOutID
public:
TestEsOutID(TestEsOut *out) { this->out = out; }
virtual ~TestEsOutID() {}
- virtual es_out_id_t * realESID() override { return nullptr; }
+ virtual es_out_id_t * realESID() const override { return nullptr; }
virtual void create() override {}
virtual void release() override {}
virtual void sendData(block_t *b) override
=====================================
modules/demux/adaptive/test/plumbing/FakeEsOut.cpp
=====================================
@@ -33,48 +33,104 @@
#include <limits>
#include <list>
#include <algorithm>
+#include <cassert>
using namespace adaptive;
using OutputVal = std::pair<const AbstractFakeESOutID *, block_t *>;
+const Times drainTimes(SegmentTimes(),std::numeric_limits<vlc_tick_t>::max());
#define DT(t) Times(SegmentTimes(), (t))
-struct context
+class DummyEsOut
{
- vlc_tick_t dts;
- vlc_tick_t pts;
- vlc_tick_t pcr;
+ public:
+ DummyEsOut();
+ ~DummyEsOut();
+
+ void reset();
+
+ static es_out_id_t *callback_add( es_out_t *, input_source_t *, const es_format_t * );
+ static int callback_send( es_out_t *, es_out_id_t *, block_t * );
+ static void callback_del( es_out_t *, es_out_id_t * );
+ static int callback_control( es_out_t *, input_source_t *, int, va_list );
+ static void callback_destroy( es_out_t * );
+
+ vlc_tick_t dts;
+ vlc_tick_t pts;
+ vlc_tick_t pcr;
+
+ class ES
+ {
+ public:
+ ES(const es_format_t *);
+ ~ES();
+ es_format_t fmt;
+ bool b_selected;
+ };
+
+ std::list<ES *> eslist;
};
+DummyEsOut::DummyEsOut()
+{
+ reset();
+}
+
+DummyEsOut::~DummyEsOut()
+{
+
+}
+
+void DummyEsOut::reset()
+{
+ dts = VLC_TICK_INVALID;
+ pts = VLC_TICK_INVALID;
+ pcr = VLC_TICK_INVALID;
+ while(!eslist.empty())
+ {
+ delete eslist.front();
+ eslist.pop_front();
+ }
+}
+
struct dropesout
{
- struct context *ctx;
+ DummyEsOut *dummyesout;
es_out_t esout;
};
-static es_out_id_t *dummy_callback_add(es_out_t *, input_source_t *, const es_format_t *)
+es_out_id_t *DummyEsOut::callback_add(es_out_t *out, input_source_t *, const es_format_t *fmt)
{
- return (es_out_id_t *) 0x01;
+ DummyEsOut *dummyesout = container_of(out, dropesout, esout)->dummyesout;
+ ES *es = new ES(fmt);
+ dummyesout->eslist.push_back(es);
+ return (es_out_id_t *) es;
}
-static int dummy_callback_send(es_out_t *out, es_out_id_t *, block_t *b)
+int DummyEsOut::callback_send(es_out_t *out, es_out_id_t *, block_t *b)
{
- struct context *ctx = container_of(out, dropesout, esout)->ctx;
- ctx->dts = b->i_dts;
- ctx->pts = b->i_pts;
+ DummyEsOut *dummyesout = container_of(out, dropesout, esout)->dummyesout;
+ dummyesout->dts = b->i_dts;
+ dummyesout->pts = b->i_pts;
block_Release(b);
return VLC_SUCCESS;
}
-static void dummy_callback_del(es_out_t *, es_out_id_t *)
+void DummyEsOut::callback_del(es_out_t *out, es_out_id_t *id)
{
-
+ DummyEsOut *dummyesout = container_of(out, dropesout, esout)->dummyesout;
+ ES *es = (ES *) id;
+ auto it = std::find(dummyesout->eslist.begin(), dummyesout->eslist.end(), es);
+ assert(it != dummyesout->eslist.end());
+ if(it != dummyesout->eslist.end())
+ dummyesout->eslist.erase(it);
+ delete es;
}
-static int dummy_callback_control(es_out_t *out, input_source_t *, int i_query, va_list args)
+int DummyEsOut::callback_control(es_out_t *out, input_source_t *, int i_query, va_list args)
{
- struct context *ctx = container_of(out, dropesout, esout)->ctx;
+ DummyEsOut *dummyesout = container_of(out, dropesout, esout)->dummyesout;
switch( i_query )
{
@@ -83,9 +139,40 @@ static int dummy_callback_control(es_out_t *out, input_source_t *, int i_query,
{
if( i_query == ES_OUT_SET_GROUP_PCR )
(void) va_arg( args, int );
- ctx->pcr = va_arg( args, vlc_tick_t );
+ dummyesout->pcr = va_arg( args, vlc_tick_t );
break;
}
+ case ES_OUT_SET_ES:
+ {
+ ES *es = (ES *) va_arg( args, es_out_id_t * );
+ /* emulate reselection */
+ for( ES *e : dummyesout->eslist )
+ {
+ if( e->fmt.i_cat == es->fmt.i_cat )
+ e->b_selected = (e == es);
+ }
+ return VLC_SUCCESS;
+ }
+ case ES_OUT_SET_ES_STATE:
+ {
+ /* emulate selection override */
+ ES *es = (ES *) va_arg( args, es_out_id_t * );
+ bool b = va_arg( args, int );
+ auto it = std::find(dummyesout->eslist.begin(), dummyesout->eslist.end(), es);
+ if(it == dummyesout->eslist.end())
+ return VLC_EGENERIC;
+ (*it)->b_selected = b;
+ return VLC_SUCCESS;
+ }
+ case ES_OUT_GET_ES_STATE:
+ {
+ ES *es = (ES *) va_arg( args, es_out_id_t * );
+ auto it = std::find(dummyesout->eslist.begin(), dummyesout->eslist.end(), es);
+ if(it == dummyesout->eslist.end())
+ return VLC_EGENERIC;
+ *va_arg( args, bool * ) = (*it)->b_selected;
+ return VLC_SUCCESS;
+ }
default:
return VLC_EGENERIC;
}
@@ -93,21 +180,33 @@ static int dummy_callback_control(es_out_t *out, input_source_t *, int i_query,
return VLC_SUCCESS;
}
-static void dummy_callback_destroy(es_out_t *)
+void DummyEsOut::callback_destroy(es_out_t *)
{
}
const struct es_out_callbacks dummycbs =
{
- .add = dummy_callback_add,
- .send = dummy_callback_send,
- .del = dummy_callback_del,
- .control = dummy_callback_control,
- .destroy = dummy_callback_destroy,
+ .add = DummyEsOut::callback_add,
+ .send = DummyEsOut::callback_send,
+ .del = DummyEsOut::callback_del,
+ .control = DummyEsOut::callback_control,
+ .destroy = DummyEsOut::callback_destroy,
.priv_control = nullptr,
};
+DummyEsOut::ES::ES(const es_format_t *src)
+{
+ b_selected = false;
+ es_format_Init(&fmt, src->i_cat, src->i_codec);
+ es_format_Copy(&fmt, src);
+}
+
+DummyEsOut::ES::~ES()
+{
+ es_format_Clean(&fmt);
+}
+
static void enqueue(es_out_t *out, es_out_id_t *id, vlc_tick_t dts, vlc_tick_t pts)
{
block_t *b = block_Alloc(1);
@@ -125,7 +224,147 @@ static void enqueue(es_out_t *out, es_out_id_t *id, vlc_tick_t dts, vlc_tick_t p
#define PCR(t) es_out_SetPCR(out, t)
#define FROM_MPEGTS(x) (INT64_C(x) * 100 / 9)
-static int check2(es_out_t *out, struct context *, FakeESOut *fakees)
+static int check3(es_out_t *out, DummyEsOut *dummy, FakeESOut *fakees)
+{
+ es_format_t fmt;
+
+ /* few ES reusability checks */
+ try
+ {
+ es_format_Init(&fmt, AUDIO_ES, VLC_CODEC_MP4A);
+ FakeESOutID fakeid0(fakees, &fmt);
+ fmt.audio.i_rate = 48000;
+ FakeESOutID fakeid1(fakees, &fmt);
+ fmt.i_original_fourcc = 0xbeef;
+ FakeESOutID fakeid2(fakees, &fmt);
+ es_format_Clean(&fmt);
+ es_format_Init(&fmt, VIDEO_ES, VLC_CODEC_H264);
+ FakeESOutID fakeid3(fakees, &fmt);
+ Expect(fakeid0.isCompatible(&fakeid0) == false); // aac without rate
+ Expect(fakeid0.isCompatible(&fakeid1) == false); // aac rate/unknown mix
+ Expect(fakeid1.isCompatible(&fakeid1) == true); // aac with same rate
+ Expect(fakeid0.isCompatible(&fakeid3) == false); // different codecs
+ Expect(fakeid1.isCompatible(&fakeid2) == false); // different original fourcc
+ Expect(fakeid2.isCompatible(&fakeid2) == true); // same original fourcc
+ Expect(fakeid3.isCompatible(&fakeid3) == false); // same video with extra codecs
+ es_format_Clean(&fmt);
+ } catch (...) {
+ return 1;
+ }
+
+ es_format_Init(&fmt, VIDEO_ES, VLC_CODEC_H264);
+ es_out_id_t *id = es_out_Add(out, &fmt);
+ try
+ {
+ Expect(id != nullptr);
+
+ /* single ES should be allocated */
+ Expect(dummy->eslist.size() == 0);
+ fakees->commandsQueue()->Commit();
+ fakees->commandsQueue()->Process(drainTimes);
+ Expect(dummy->eslist.size() == 1);
+ Expect(dummy->eslist.front()->fmt.i_codec == VLC_CODEC_H264);
+ dummy->eslist.front()->b_selected = true; /* fake selection */
+
+ /* subsequent ES should be allocated */
+ es_format_Clean(&fmt);
+ es_format_Init(&fmt, AUDIO_ES, VLC_CODEC_MP4A);
+ id = es_out_Add(out, &fmt);
+ fakees->commandsQueue()->Commit();
+ fakees->commandsQueue()->Process(drainTimes);
+ Expect(dummy->eslist.size() == 2);
+ Expect(dummy->eslist.front()->fmt.i_codec == VLC_CODEC_H264);
+ Expect(dummy->eslist.front()->b_selected == true);
+ Expect(dummy->eslist.back()->fmt.i_codec == VLC_CODEC_MP4A);
+
+ /* on restart / new segment, unused ES should be reclaimed */
+ fakees->recycleAll();
+ es_format_Clean(&fmt);
+ es_format_Init(&fmt, VIDEO_ES, VLC_CODEC_MPGV);
+ id = es_out_Add(out, &fmt);
+ fakees->commandsQueue()->Commit();
+ fakees->commandsQueue()->Process(drainTimes);
+ Expect(dummy->eslist.size() == 3);
+ fakees->gc();
+ Expect(dummy->eslist.size() == 1);
+ Expect(dummy->eslist.front()->fmt.i_codec == VLC_CODEC_MPGV);
+ Expect(dummy->eslist.front()->b_selected == true);
+
+ /* on restart / new segment, ES MUST be reused */
+ fakees->recycleAll();
+ Expect(dummy->eslist.size() == 1);
+ es_format_Clean(&fmt);
+ es_format_Init(&fmt, VIDEO_ES, VLC_CODEC_MPGV);
+ /* check ID signaling so we don't blame FakeEsOut */
+ {
+ FakeESOutID fakeid(fakees, &fmt);
+ Expect(fakeid.isCompatible(&fakeid));
+ }
+ id = es_out_Add(out, &fmt);
+ fakees->commandsQueue()->Commit();
+ fakees->commandsQueue()->Process(drainTimes);
+ Expect(dummy->eslist.size() == 1);
+ fakees->gc();
+ Expect(dummy->eslist.size() == 1);
+ Expect(dummy->eslist.front()->b_selected == true);
+
+ /* on restart / new segment, different codec, ES MUST NOT be reused */
+ fakees->recycleAll();
+ Expect(dummy->eslist.size() == 1);
+ es_format_Clean(&fmt);
+ es_format_Init(&fmt, VIDEO_ES, VLC_CODEC_H264);
+ id = es_out_Add(out, &fmt);
+ es_format_Clean(&fmt);
+ es_format_Init(&fmt, AUDIO_ES, VLC_CODEC_MP4A);
+ id = es_out_Add(out, &fmt);
+ fakees->commandsQueue()->Commit();
+ fakees->commandsQueue()->Process(drainTimes);
+ Expect(dummy->eslist.size() == 3);
+ fakees->gc();
+ Expect(dummy->eslist.size() == 2);
+ for( DummyEsOut::ES *e : dummy->eslist ) /* selection state must have been kept */
+ if( e->fmt.i_cat == VIDEO_ES )
+ Expect(e->b_selected == true);
+
+ /* on restart / new segment, incompatible codec parameters, ES MUST NOT be reused */
+ fakees->recycleAll();
+ Expect(dummy->eslist.size() == 2);
+ es_format_Clean(&fmt);
+ es_format_Init(&fmt, VIDEO_ES, VLC_CODEC_H264);
+ id = es_out_Add(out, &fmt);
+ /* check ID signaling so we don't blame FakeEsOut */
+ {
+ FakeESOutID fakeid(fakees, &fmt);
+ Expect(fakeid.isCompatible(&fakeid) == false);
+ }
+ es_format_Clean(&fmt);
+ es_format_Init(&fmt, AUDIO_ES, VLC_CODEC_MP4A);
+ id = es_out_Add(out, &fmt);
+ /* check ID signaling so we don't blame FakeEsOut */
+ {
+ FakeESOutID fakeid(fakees, &fmt);
+ Expect(fakeid.isCompatible(&fakeid) == false);
+ }
+ fakees->commandsQueue()->Commit();
+ fakees->commandsQueue()->Process(drainTimes);
+ Expect(dummy->eslist.size() == 4);
+ fakees->gc();
+ Expect(dummy->eslist.size() == 2);
+ for( DummyEsOut::ES *e : dummy->eslist ) /* selection state must have been kept */
+ if( e->fmt.i_cat == VIDEO_ES )
+ Expect(e->b_selected == true);
+
+ } catch (...) {
+ return 1;
+ }
+
+ es_format_Clean(&fmt);
+
+ return 0;
+}
+
+
+static int check2(es_out_t *out, DummyEsOut *, FakeESOut *fakees)
{
es_format_t fmt;
es_format_Init(&fmt, VIDEO_ES, VLC_CODEC_H264);
@@ -208,7 +447,7 @@ static int check2(es_out_t *out, struct context *, FakeESOut *fakees)
return 0;
}
-static int check1(es_out_t *out, struct context *ctx, FakeESOut *fakees)
+static int check1(es_out_t *out, DummyEsOut *ctx, FakeESOut *fakees)
{
es_format_t fmt;
es_format_Init(&fmt, VIDEO_ES, VLC_CODEC_H264);
@@ -216,6 +455,7 @@ static int check1(es_out_t *out, struct context *ctx, FakeESOut *fakees)
/* ensure ES is created */
const Times drainTimes(SegmentTimes(),std::numeric_limits<vlc_tick_t>::max());
+
fakees->commandsQueue()->Commit();
fakees->commandsQueue()->Process(drainTimes);
@@ -328,7 +568,7 @@ static int check1(es_out_t *out, struct context *ctx, FakeESOut *fakees)
return 0;
}
-static int check0(es_out_t *out, struct context *, FakeESOut *fakees)
+static int check0(es_out_t *out, DummyEsOut *, FakeESOut *fakees)
{
es_format_t fmt;
es_format_Init(&fmt, VIDEO_ES, VLC_CODEC_H264);
@@ -374,21 +614,25 @@ static int check0(es_out_t *out, struct context *, FakeESOut *fakees)
int FakeEsOut_test()
{
- struct context ctx = {VLC_TICK_INVALID,VLC_TICK_INVALID,VLC_TICK_INVALID};
- struct dropesout dummy = { .ctx = &ctx, .esout = { .cbs = &dummycbs } };
-
- int(* const tests[3])(es_out_t *, struct context *, FakeESOut *)
- = { check0, check1, check2 };
- for(size_t i=0; i<3; i++)
+ DummyEsOut dummyEsOut;
+ struct dropesout dummy = {
+ .dummyesout = &dummyEsOut,
+ .esout = { .cbs = &dummycbs }
+ };
+
+ int(* const tests[4])(es_out_t *, DummyEsOut *, FakeESOut *)
+ = { check0, check1, check2, check3 };
+ for(size_t i=0; i<4; i++)
{
CommandsFactory *factory = new CommandsFactory();
CommandsQueue *queue = new CommandsQueue();
FakeESOut *fakees = new FakeESOut(&dummy.esout, queue, factory);
es_out_t *out = *fakees;
- int ret = tests[i](out, &ctx, fakees);
+ int ret = tests[i](out, &dummyEsOut, fakees);
delete fakees;
if (ret)
return ret;
+ dummyEsOut.reset();
}
return 0;
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a0f1dc38fa722e210b7b0eb85124550f051c373a...479e9f3fcbce1ae0283004606e4f7a00e6195647
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a0f1dc38fa722e210b7b0eb85124550f051c373a...479e9f3fcbce1ae0283004606e4f7a00e6195647
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list