Project

General

Profile

Actions

Support Request #18068

closed

AcceptType won't be called when using ProcessInput(base::flash::tNanoSeconds, streaming::flash::ISampleReader*)

Added by hidden over 1 year ago. Updated about 1 year ago.

Status:
Closed
Priority:
Normal
Customer:
CARIAD
Department:
Requester's Priority:
Normal
Support Level:
2nd Level
Resolution:
Solved Issue
Product Issue Numbers:
Affected Products:
Platform:
Windows 10 64bit
Topic:
ADTF::SDK
FAQ Links:

Description

Supportanfrage

Ich versuche herauszufinden, warum in bestimmten Fällen die AcceptType zur Verifikation der Kompatibilität der Streams nicht aufgerufen wird.
Ich habe dazu den Test im Anhang geschrieben.

Während die Datenkommunikation offenbar funktioniert (ProcessInput wird gerufen), scheint keine Typprüfung stattzufinden (AcceptType wird NICHT gerufen).
Was habe ich übersehen?

Lösung

Im ersten Moment ist das verwirrend, es gibt aber eine simple logische Erklärung:
  • Die AcceptType() (oder natürlich dein eigenes SetAcceptTypeCallback()) wir nur gerufen, wenn am reader auch ein sample gelesen wird.
  • In der von dir verwendeten ProcessInput() mit dem reader bist du selbst dafür verantwortlich, die samples aus der queue zu holen. Deshalb brauchst du mindestens ein GetLastSample() / GetNextSample()
  • Alternativ kannst du die ProcessInput() mit dem sample nehmen, hier ist das sample bereits geholt, dadurch wird automatisch der type im Vorfeld geprüft (weil das Sample bereits vorher geholt wurde, siehe Reihenfolge der ProcessInput Calls) und auch nur dann diese ProcessInput() gerufen, wenn das sample bzw. der type akzeptiert wird

Folgende Tests veranschaulichen das:

ProcessInput mit Reader

ProcessInput mit Sample

ProcessInput mit Sample Data

in ADTF 3.15 versuchen wir das bei der Doku zu den API Funktionen zu verdeutlichen.


Files

image003.png (7.36 KB) image003.png hidden, 2022-08-11 19:30
adtf_test.cpp (6.54 KB) adtf_test.cpp hidden, 2022-08-11 19:30
Actions #1

Updated by hidden over 1 year ago

  • Project changed from Public Support to 30
  • Status changed from New to In Progress
  • Customer set to CARIAD
  • Affected Products ADTF 3.13.5 added
  • Platform Windows 10 64bit added
Actions #2

Updated by hidden over 1 year ago

  • Topic set to ADTF::SDK
Actions #4

Updated by hidden over 1 year ago

  • Status changed from In Progress to Customer Feedback Required

Hi Jens,

im ersten Moment ist das verwirrend, es gibt aber eine simple logische Erklärung:

Ich habe mal deinen Test etwas abgespeckt, statt einen Sender einen cTestWriter, alles ohne Graph und versucht dass es so leserlich ist, was passiert.
Geht natürlich auch so wie bei dir, kannst du dir aber sparen an Overhead...

Ich glaube das sind die Schritte, die du sehen wolltest.


ProcessInput mit Reader

#include <adtffiltersdk/adtf_filtersdk.h>
#include <adtfsystemsdk/testing/test_system.h>
#include <adtftesting/adtf_testing.h>

using namespace adtf::ucom;
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::filter;
using namespace adtf::filter::testing;
using namespace adtf::system::testing;

class cReceiverFilter : public cFilter
{
public:
    ADTF_CLASS_ID_NAME(cReceiverFilter, "receiverfilter.test.cid", "Receiver Filter");

    cReceiverFilter()
    {
        object_ptr<IStreamType> pType = make_object_ptr<stream_type_plain<int32_t>>();
        m_pReader = CreateInputPin("input", pType);
    }

    tResult AcceptType(ISampleReader* pReader, const iobject_ptr<const IStreamType>& pType) override
    {
        ++m_nAcceptTypeCallCount;

        RETURN_IF_FAILED(cFilter::AcceptType(pReader, pType));

        ++m_nAcceptSampleCount;

        RETURN_NOERROR;
    }

    tResult ProcessInput(tNanoSeconds tmTrigger, ISampleReader* pReader) override
    {
        ++m_nReceivedSampleCount;

        // Note: It is important to get the sample from the queue to trigger the type check
        // Using ProcessInput(tNanoSeconds tmTrigger, ISampleReader* pReader) means you have to read the sample.
        // The ProcessInput(ISampleReader* pReader, const iobject_ptr<const ISample>& pSample) will do it for you, the sample has already be read
        object_ptr<const ISample> pSample;
        return m_pReader->GetLastSample(pSample);
    }

private:
    ISampleReader* m_pReader = nullptr;

public:
    int m_nAcceptTypeCallCount = 0;
    int m_nReceivedSampleCount = 0;
    int m_nAcceptSampleCount = 0;
};

struct MyTestSystem : cTestSystem
{
    MyTestSystem(){};
};

TEST_CASE_METHOD(MyTestSystem, "AcceptType using ProcessInput(tNanoSeconds tmTrigger, ISampleReader* pReader)")
{
    auto pReceiverFilter = make_object_ptr<cReceiverFilter>();

    cTestWriter oWriter(pReceiverFilter, "input", stream_type_plain<double>());

    REQUIRE_OK(pReceiverFilter->SetState(adtf::streaming::IFilter::tFilterState::State_Running));

    SECTION("Initial check")
    {
        REQUIRE(0 == pReceiverFilter->m_nReceivedSampleCount);
        REQUIRE(0 == pReceiverFilter->m_nAcceptTypeCallCount);
        REQUIRE(0 == pReceiverFilter->m_nAcceptSampleCount);
    }

    oWriter.Write<double>(42.0, true);

    SECTION("Invalid stream type has been written: ProcessInput wil be triggered, but sample won't be accepted")
    {
        REQUIRE(1 == pReceiverFilter->m_nReceivedSampleCount);
        REQUIRE(1 == pReceiverFilter->m_nAcceptTypeCallCount);
        REQUIRE(0 == pReceiverFilter->m_nAcceptSampleCount);
    }

    oWriter.ChangeType(stream_type_plain<int32_t>());
    oWriter.Write<int32_t>(42, true);

    SECTION("Valid stream type has been written: ProcessInput wil be triggered, sample will be accepted")
    {
        REQUIRE(2 == pReceiverFilter->m_nReceivedSampleCount);
        REQUIRE(2 == pReceiverFilter->m_nAcceptTypeCallCount);
        REQUIRE(1 == pReceiverFilter->m_nAcceptSampleCount);
    }
}

ProcessInput mit Sample

#include <adtffiltersdk/adtf_filtersdk.h>
#include <adtfsystemsdk/testing/test_system.h>
#include <adtftesting/adtf_testing.h>

using namespace adtf::ucom;
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::filter;
using namespace adtf::filter::testing;
using namespace adtf::system::testing;

class cReceiverFilter : public cFilter
{
public:
    ADTF_CLASS_ID_NAME(cReceiverFilter, "receiverfilter.test.cid", "Receiver Filter");

    cReceiverFilter()
    {
        object_ptr<IStreamType> pType = make_object_ptr<stream_type_plain<int32_t>>();
        m_pReader = CreateInputPin("input", pType);
    }

    tResult AcceptType(ISampleReader* pReader, const iobject_ptr<const IStreamType>& pType) override
    {
        ++m_nAcceptTypeCallCount;

        RETURN_IF_FAILED(cFilter::AcceptType(pReader, pType));

        ++m_nAcceptSampleCount;

        RETURN_NOERROR;
    }

    tResult ProcessInput(ISampleReader* pReader, const iobject_ptr<const ISample>& pSample) override
    {
        ++m_nReceivedSampleCount;
        RETURN_NOERROR;
    }

private:
    ISampleReader* m_pReader = nullptr;

public:
    int m_nAcceptTypeCallCount = 0;
    int m_nReceivedSampleCount = 0;
    int m_nAcceptSampleCount = 0;
};

struct MyTestSystem : cTestSystem
{
    MyTestSystem(){};
};

TEST_CASE_METHOD(MyTestSystem, "AcceptType using ProcessInput(ISampleReader* pReader, const iobject_ptr<const ISample>& pSample)")
{
    auto pReceiverFilter = make_object_ptr<cReceiverFilter>();

    cTestWriter oWriter(pReceiverFilter, "input", stream_type_plain<double>());

    REQUIRE_OK(pReceiverFilter->SetState(adtf::streaming::IFilter::tFilterState::State_Running));

    SECTION("Initial check")
    {
        REQUIRE(0 == pReceiverFilter->m_nReceivedSampleCount);
        REQUIRE(0 == pReceiverFilter->m_nAcceptTypeCallCount);
        REQUIRE(0 == pReceiverFilter->m_nAcceptSampleCount);
    }

    oWriter.Write<double>(42.0, true);

    SECTION("Invalid stream type has been written: sample won't be accepted, ProcessInput won't be triggered")
    {
        REQUIRE(0 == pReceiverFilter->m_nReceivedSampleCount);
        REQUIRE(1 == pReceiverFilter->m_nAcceptTypeCallCount);
        REQUIRE(0 == pReceiverFilter->m_nAcceptSampleCount);
    }

    oWriter.ChangeType(stream_type_plain<int32_t>());
    oWriter.Write<int32_t>(42, true);

    SECTION("Valid stream type has been written: sample will be accepted, ProcessInput will be triggered")
    {
        REQUIRE(1 == pReceiverFilter->m_nReceivedSampleCount);
        REQUIRE(2 == pReceiverFilter->m_nAcceptTypeCallCount);
        REQUIRE(1 == pReceiverFilter->m_nAcceptSampleCount);
    }
}

Beantwortet das dein Anliegen ?
Ich bin gerade noch am tüfteln, wie ich das in der Doku abbilde...

Actions #5

Updated by hidden over 1 year ago

Nachtrag:

Gilt natürlich auch für ProcessInput() mit Sample Data
Im Prinzip hast du im ersten Schuss die einzige der drei möglich ProcessInput() Funktionen genommen, wo du das sample noch abholen musst :-)

Zur Vollständigkeit auch

ProcessInput mit Sample Data

#include <adtffiltersdk/adtf_filtersdk.h>
#include <adtfsystemsdk/testing/test_system.h>
#include <adtftesting/adtf_testing.h>

using namespace adtf::ucom;
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::filter;
using namespace adtf::filter::testing;
using namespace adtf::system::testing;

class cReceiverFilter : public cFilter
{
public:
    ADTF_CLASS_ID_NAME(cReceiverFilter, "receiverfilter.test.cid", "Receiver Filter");

    cReceiverFilter()
    {
        object_ptr<IStreamType> pType = make_object_ptr<stream_type_plain<int32_t>>();
        m_pReader = CreateInputPin("input", pType);
    }

    tResult AcceptType(ISampleReader* pReader, const iobject_ptr<const IStreamType>& pType) override
    {
        ++m_nAcceptTypeCallCount;

        RETURN_IF_FAILED(cFilter::AcceptType(pReader, pType));

        ++m_nAcceptSampleCount;

        RETURN_NOERROR;
    }

    tResult ProcessInput(ISampleReader* pReader, tNanoSeconds tmSample, const void* pSampleData, size_t nSampleDataSize) override
    {
        ++m_nReceivedSampleCount;
        RETURN_NOERROR;
    }

private:
    ISampleReader* m_pReader = nullptr;

public:
    int m_nAcceptTypeCallCount = 0;
    int m_nReceivedSampleCount = 0;
    int m_nAcceptSampleCount = 0;
};

struct MyTestSystem : cTestSystem
{
    MyTestSystem(){};
};

TEST_CASE_METHOD(MyTestSystem, "AcceptType using ProcessInput(ISampleReader* pReader, tNanoSeconds tmSample, const void* pSampleData, size_t nSampleDataSize)")
{
    auto pReceiverFilter = make_object_ptr<cReceiverFilter>();

    cTestWriter oWriter(pReceiverFilter, "input", stream_type_plain<double>());

    REQUIRE_OK(pReceiverFilter->SetState(adtf::streaming::IFilter::tFilterState::State_Running));

    SECTION("Initial check")
    {
        REQUIRE(0 == pReceiverFilter->m_nReceivedSampleCount);
        REQUIRE(0 == pReceiverFilter->m_nAcceptTypeCallCount);
        REQUIRE(0 == pReceiverFilter->m_nAcceptSampleCount);
    }

    oWriter.Write<double>(42.0, true);

    SECTION("Invalid stream type has been written: sample won't be accepted, ProcessInput won't be triggered")
    {
        REQUIRE(0 == pReceiverFilter->m_nReceivedSampleCount);
        REQUIRE(1 == pReceiverFilter->m_nAcceptTypeCallCount);
        REQUIRE(0 == pReceiverFilter->m_nAcceptSampleCount);
    }

    oWriter.ChangeType(stream_type_plain<int32_t>());
    oWriter.Write<int32_t>(42, true);

    SECTION("Valid stream type has been written: sample will be accepted, ProcessInput will be triggered")
    {
        REQUIRE(1 == pReceiverFilter->m_nReceivedSampleCount);
        REQUIRE(2 == pReceiverFilter->m_nAcceptTypeCallCount);
        REQUIRE(1 == pReceiverFilter->m_nAcceptSampleCount);
    }
}
Actions #6

Updated by hidden over 1 year ago

EDIT:
Korrekturen in #18068#note-5 vorgenommen

Actions #8

Updated by hidden over 1 year ago

Danke :).
Ich konnte durch pReader->GetLastSample den Aufruf von AcceptType bewirken. Der Hinweis mit den anderen Signaturen, die das implizit tun ist auch hilfreich.

Oft verwende ich eigenen Klassen im Test, weil ich die schnell anpassen kann, wenn ich mal schnell zusätzliche Informationen oder Funktionalitäten brauche.

Doku ist immer ein Thema. Wenn ihr hier was habt, kann ich gern mal drüber schauen.
Ansonsten kann dieses Ticket für mich hier geschlossen werden.

Actions #9

Updated by hidden over 1 year ago

  • Project changed from 30 to Public Support
  • Subject changed from AcceptType wird nicht gerufen to AcceptType won't be called when using ProcessInput(base::flash::tNanoSeconds, streaming::flash::ISampleReader*)
  • Description updated (diff)
  • Status changed from Customer Feedback Required to To Be Closed
  • Private changed from Yes to No
Actions #10

Updated by hidden over 1 year ago

  • Resolution set to Solved Issue

@Flo, ja die können wir mal übernehmen, im Filter SDK.

Actions #11

Updated by hidden about 1 year ago

  • Status changed from To Be Closed to Closed
Actions

Also available in: Atom PDF