Project

General

Profile

Support Request #14449 » iodevicefilter.cpp

hidden, 2021-06-09 06:06

 
1
/**
2
 *
3
 * Base I/O device filter implementation.
4
 *
5
 * @file
6
 * Copyright © Audi Electronics Venture GmbH. All rights reserved.
7
 *
8
 * $Author: VG8D3AW $
9
 * $Date: 2014-03-31 16:30:15 +0200 (Mon, 31 Mär 2014) $
10
 * $Revision: 45827 $
11
 * @remarks
12
 *
13
 */
14
#include "stdafx.h"
15
#include <adtf_plugin_sdk.h>
16
using namespace ucom;
17

    
18
namespace adtf
19
{
20

    
21
//*************************************************************************************************
22
class cDeviceControl : public cKernelCyclicThread
23
{
24
    protected:
25
        IDeviceTrigger* m_pTarget;
26

    
27
    public:
28
        cDeviceControl(cBaseIODeviceFilter* pFilter);
29
        virtual ~cDeviceControl();
30

    
31
        tResult Create(IDeviceTrigger* pTarget);
32
        tResult Unref();
33

    
34
        tResult Run();
35
        tResult Stop();
36

    
37
        virtual tResult CyclicFunc();
38

    
39
    private:
40
        cBaseIODeviceFilter* m_pFilter;
41
};
42

    
43
//*************************************************************************************************
44
cDeviceControl::cDeviceControl(cBaseIODeviceFilter* pFilter) : cKernelCyclicThread()
45
{
46
    #ifdef _DEBUG
47
//         SetName("Device Control Tread"); // specify debug info
48
    #endif // _DEBUG
49

    
50
    m_pFilter = pFilter;
51
    m_pTarget = NULL;
52
}
53

    
54
//*************************************************************************************************
55
cDeviceControl::~cDeviceControl()
56
{
57
    Unref();
58
}
59

    
60
//*************************************************************************************************
61
tResult cDeviceControl::Create(IDeviceTrigger* pTarget)
62
{
63
    RETURN_IF_POINTER_NULL(pTarget);
64

    
65
    m_pTarget = pTarget;
66

    
67
    cString strID = "device";
68
    ucom::cObjectPtr<ucom::IObjectInfo> pFilterInfo;
69
    if (IS_OK(m_pFilter->GetInterface(IID_OBJECT_INFO, (tVoid**) &pFilterInfo)))
70
    {
71
        strID = pFilterInfo->OIGetInstanceName();
72
    }
73

    
74
    // create thread
75
    RETURN_IF_FAILED(cKernelCyclicThread::Create(cThread::TF_Suspended, NULL, NULL, 0, strID + ".devicecontrol_thread"));
76

    
77
    RETURN_NOERROR;
78
}
79

    
80
//*************************************************************************************************
81
tResult cDeviceControl::Run()
82
{
83
    cKernelCyclicThread::Run();
84

    
85
    RETURN_NOERROR;
86
}
87

    
88
//*************************************************************************************************
89
tResult cDeviceControl::Stop()
90
{
91
    if (cKernelCyclicThread::GetState() == cKernelCyclicThread::TS_Running)
92
    {
93
        cKernelCyclicThread::Suspend(tTrue);
94
    }
95

    
96
    RETURN_NOERROR;
97
}
98

    
99
//*************************************************************************************************
100
tResult cDeviceControl::Unref()
101
{
102
    cKernelCyclicThread::Release();
103

    
104
    RETURN_NOERROR;
105
}
106

    
107
//*************************************************************************************************
108
tResult cDeviceControl::CyclicFunc()
109
{
110
    m_pTarget->OnDeviceTrigger(NULL);
111

    
112
    RETURN_NOERROR;
113
}
114

    
115
/**************************************************************************/
116
/* Private implementation to provide object compatibility                 */
117
/**************************************************************************/
118
class cBaseIODeviceFilter::cBaseIODeviceFilterPrivate : public cADTFD<cBaseIODeviceFilter, cBaseIODeviceFilter::cBaseIODeviceFilterPrivate>
119
{
120
    friend class cBaseIODeviceFilter;
121
    public:
122
        cBaseIODeviceFilterPrivate(){};
123
        virtual ~cBaseIODeviceFilterPrivate(){};
124
};
125

    
126
//*************************************************************************************************
127
const tChar* cBaseIODeviceFilter::m_strDefaultDeviceName = "default";
128

    
129
//*************************************************************************************************
130
cBaseIODeviceFilter::cBaseIODeviceFilter(const tChar* __info) : cFilter(__info) 
131
{
132
    //d-pointer implementation not yet in use
133
    //ADTF_D_CREATE(cBaseIODeviceFilter);
134

    
135
    m_pDevice                           = NULL;
136
    m_pTriggerThread                    = NULL;
137
    m_pStatistics                       = NULL;
138

    
139
    // predefine properties
140
    SetPropertyStr("devicename",        m_strDefaultDeviceName);
141
    SetPropertyStr("devicename" NSSUBPROP_DESCRIPTION,
142
                   "Name of device to be used.");
143

    
144
    SetPropertyFloat("updaterate",        0);
145
    SetPropertyStr("updaterate" NSSUBPROP_DESCRIPTION,
146
                   "Limits the rate at which the device thread gets called. Use 0 to disable limitation.");
147

    
148
    SetPropertyBool("syncenable",       tTrue);
149
    SetPropertyStr("syncenable" NSSUBPROP_DESCRIPTION,
150
                   "If set to true each transmitted mediasample will be marked with the MSF_SyncPoint flag.");
151
}
152

    
153
//*************************************************************************************************
154
cBaseIODeviceFilter::~cBaseIODeviceFilter()
155
{
156
}
157

    
158
//*************************************************************************************************
159
tResult cBaseIODeviceFilter::Init(cFilter::tInitStage eStage, ucom::IException** __exception_ptr)
160
{
161
    if (eStage == StageFirst)
162
    {
163
        m_pTriggerThread = NULL;
164

    
165
        m_f32UpdateRate = (tFloat32) GetPropertyFloat("updaterate");
166
     
167
        m_bSyncEnable = GetPropertyBool("SyncEnable");
168
        RETURN_IF_FAILED(OnCreatePins());
169
    }
170
    else if (eStage == StageNormal)
171
    {
172
        tResult nResult = ERR_NOERROR;
173

    
174
        cString strDeviceName = GetPropertyStr("DeviceName");
175
        if (strDeviceName.IsEmpty())
176
        {
177
            strDeviceName = GetPropertyStr("Source");
178

    
179
            if (strDeviceName.IsEmpty())
180
            {
181
                strDeviceName = m_strDefaultDeviceName;
182
            }
183
        }
184
        else
185
        {
186
            cString strNameLeft = strDeviceName.Left(8);
187
            if (cString::IsEqualNoCase(strNameLeft, "capture:"))
188
            {
189
                strDeviceName.Delete(0, 8);
190
            }
191
        }
192

    
193
        cString strFilterName = OIGetInstanceName();
194
        if (strFilterName.IsEmpty())
195
        {
196
            strFilterName = "Unnamed IO Device";
197
        }
198

    
199
        m_pStatistics = new cStatistics(strFilterName);
200

    
201
        if ( m_f32UpdateRate > 0)
202
        {
203
            m_nMinDelay = (tTimeStamp) (1000000 / m_f32UpdateRate);
204
        }
205
        else
206
        {
207
           m_nMinDelay = 0;
208
        }
209

    
210
        tInt nDeviceStatus;
211

    
212
        // ---- open device ----
213
        nResult = m_pDevice->Open(strDeviceName.GetPtr(), IDevice::DM_Read, __exception_ptr);
214
        if (IS_FAILED(nResult))
215
        {
216
            if (__exception_ptr != NULL)
217
            {
218
                __catch_exception(*__exception_ptr)
219
                {
220
                    //just forward error code 
221
                   RETURN_ERROR((*__exception_ptr)->GetResult());
222
                }
223
            }
224
            THROW_ERROR_DESC(nResult, "Could not open device");
225
        }
226

    
227
        IDevice::tDeviceInfo sDeviceInfo;
228
        nDeviceStatus = m_pDevice->IOCtl(IDevice::IOCTL_GetDeviceInfo, &sDeviceInfo, sizeof(sDeviceInfo));
229
        if (0 > nDeviceStatus)
230
        {
231
            THROW_ERROR_DESC(ERR_DEVICE_NOT_READY, "Could not query device info");
232
        }
233

    
234
        m_pDevice->IOCtl(IDevice::IOCTL_RegisterHandler, static_cast<IDeviceEventHandler*> (this));
235

    
236
        // ---- initialize device control thread ----
237
        m_pTriggerThread = new cDeviceControl(this);
238
        if (m_pTriggerThread == NULL)
239
        {
240
            THROW_ERROR_DESC(ERR_MEMORY, "Could not create device control thread");
241
        }
242

    
243
        nResult = ((cDeviceControl*) m_pTriggerThread)->Create(this);
244
        if (IS_FAILED(nResult))
245
        {
246
            THROW_ERROR_DESC(nResult, "Could not initialize device control thread");
247
        }
248

    
249
        // if read is non-blocking for device, the control
250
        // thread has to take care about synchronizing the calls
251
        tInt nCycleTime = 0;
252
        if ((sDeviceInfo.ui32Flags & IDevice::DF_AsyncIO) != 0)
253
        {
254
            nCycleTime = (tInt) m_nMinDelay;
255
        }
256
        THROW_IF_FAILED(((cDeviceControl*) m_pTriggerThread)->SetCycleTime(nCycleTime));
257
    }
258

    
259
    return cFilter::Init(eStage, __exception_ptr);
260
}
261

    
262
//*************************************************************************************************
263
tResult cBaseIODeviceFilter::Start(ucom::IException** __exception_ptr)
264
{
265
    m_nLastDataTime = -1;
266

    
267
    m_pStatistics->Reset();
268

    
269
    if (m_pTriggerThread != NULL)
270
    {
271
        ((cDeviceControl*) m_pTriggerThread)->Run();
272
    }
273

    
274
    return cFilter::Start(__exception_ptr);
275
}
276

    
277
//*************************************************************************************************
278
tResult cBaseIODeviceFilter::Stop(ucom::IException** __exception_ptr)
279
{
280
    if (m_pTriggerThread != NULL)
281
    {
282
        ((cDeviceControl*) m_pTriggerThread)->Stop();
283
    }
284

    
285
    return cFilter::Stop(__exception_ptr);
286
}
287

    
288
//*************************************************************************************************
289
tResult cBaseIODeviceFilter::Shutdown(cFilter::tInitStage eStage, ucom::IException** __exception_ptr)
290
{
291
    if (m_pTriggerThread != NULL)
292
    {
293
        ((cDeviceControl*) m_pTriggerThread)->Release();
294
        delete (cDeviceControl*) m_pTriggerThread;
295
        m_pTriggerThread = NULL;
296
    }
297

    
298
    if (m_pDevice != NULL)
299
    {
300
        m_pDevice->IOCtl(IDevice::IOCTL_UnregisterHandler, static_cast<IDeviceEventHandler*> (this));
301
        m_pDevice->Close();
302
    }
303

    
304
    if (m_pStatistics != NULL)
305
    {
306
        delete m_pStatistics;
307
        m_pStatistics = NULL;
308
    }
309

    
310
    cFilter::Shutdown(eStage, __exception_ptr);
311

    
312
    RETURN_NOERROR;
313
}
314

    
315
tResult cBaseIODeviceFilter::OnDeviceTrigger(tVoid* pvUserData)
316
{
317
    return ReadAndTransmitData();
318
}
319

    
320
tResult cBaseIODeviceFilter::CheckUpdateRate()
321
{
322
    if (NULL == _clock)
323
    {
324
        RETURN_NOERROR;
325
    }
326

    
327
    tTimeStamp tmTimeStamp = _clock->GetStreamTime();
328

    
329
    if (m_nMinDelay != 0)
330
    {
331
        if (m_nLastDataTime != -1 &&
332
            (tmTimeStamp - m_nLastDataTime) < m_nMinDelay)
333
        {
334
            // drop data due to frame rate limitation.
335
            RETURN_ERROR(ERR_CANCELLED);
336
        }
337

    
338
        m_nLastDataTime += m_nMinDelay;
339

    
340
        if ((tmTimeStamp - m_nLastDataTime) > m_nMinDelay)
341
        {
342
            m_nLastDataTime = tmTimeStamp - m_nMinDelay;
343
        }
344
        else if (m_nLastDataTime > tmTimeStamp)
345
        {
346
            m_nLastDataTime = tmTimeStamp;
347
        }
348
    }
349

    
350
    RETURN_NOERROR;
351
}
352

    
353
tResult cBaseIODeviceFilter::ReadAndTransmitData()
354
{
355
    if (IS_FAILED(CheckUpdateRate()))
356
    {
357
        RETURN_NOERROR;
358
    }
359

    
360
    tTimeStamp tmTimeStamp = 0;
361
    
362
    if (NULL != _clock)
363
    {
364
        tmTimeStamp = _clock->GetStreamTime();
365
    }
366

    
367
    tInt nDeviceStatus = m_pDevice->IOCtl(IDevice::IOCTL_GetDataSize);
368
    if (0 > nDeviceStatus)
369
    {
370
        LOG_ERROR("device not ready");
371
        RETURN_ERROR(ERR_DEVICE_NOT_READY);
372
    }
373

    
374
    if (0 == nDeviceStatus)
375
    {
376
        RETURN_NOERROR;
377
    }
378

    
379
    tInt nBufferSize = nDeviceStatus;
380

    
381
    cObjectPtr<IMediaSample> pNewSample;
382
    RETURN_IF_FAILED(_runtime->CreateInstance(OID_ADTF_MEDIA_SAMPLE, IID_ADTF_MEDIA_SAMPLE, (tVoid**) &pNewSample));
383

    
384
    RETURN_IF_FAILED(pNewSample->AllocBuffer(nBufferSize));
385

    
386
    tVoid* pBuffer;
387
    RETURN_IF_FAILED(pNewSample->WriteLock(&pBuffer));
388

    
389
    nDeviceStatus = m_pDevice->Read(pBuffer, nBufferSize);
390

    
391
    pNewSample->Unlock(pBuffer);
392

    
393
    if (0 == nDeviceStatus)
394
    {
395
        // no data
396
        RETURN_NOERROR;
397
    }
398

    
399
    if (-1 == nDeviceStatus)
400
    {
401
        LOG_ERROR("could not read from device");
402
        RETURN_ERROR(ERR_DEVICE_IO);
403
    }
404

    
405
    tTimeStamp tmSample;
406
    nDeviceStatus = m_pDevice->IOCtl(IDevice::IOCTL_GetDataTime, &tmSample, sizeof(tmSample));
407
    if (0 > nDeviceStatus)
408
    {
409
        tmSample = tmTimeStamp;
410
    }
411
    else
412
    {
413
        tmSample = Sync2RefTime(tmSample);
414
    }
415

    
416
    pNewSample->SetTime(tmSample);
417
    pNewSample->SetFlags(m_bSyncEnable ? IMediaSample::MSF_SyncPoint : IMediaSample::MSF_None);
418

    
419
    OnTransmitData(pNewSample);
420

    
421
    m_pStatistics->Update();
422

    
423
    RETURN_NOERROR;
424
}
425

    
426
//*************************************************************************************************
427
tResult cBaseIODeviceFilter::OnCreatePins()
428
{
429
    RETURN_ERROR(ERR_NOT_IMPL);
430
}
431

    
432
//*************************************************************************************************
433
tResult cBaseIODeviceFilter::OnTransmitData(IMediaSample* pSample)
434
{
435
    RETURN_ERROR(ERR_NOT_IMPL);
436
}
437

    
438
//*************************************************************************************************
439
tResult cBaseIODeviceFilter::OnGetMediaType(IMediaType** ppMediaType)
440
{
441
    RETURN_ERROR(ERR_NOT_IMPL);
442
}
443

    
444
//*************************************************************************************************
445
tResult cBaseIODeviceFilter::OnDeviceEvent(tInt nEventId, tInt nParam1, tInt nParam2, tVoid* pvData, tInt nDataSize)
446
{
447
    if (nEventId == IDeviceEventHandler::DE_NewData)
448
    {
449
        ReadAndTransmitData();
450
        RETURN_NOERROR;
451
    }
452

    
453
    RETURN_ERROR(ERR_NOT_IMPL);
454
}
455

    
456
} // namespace adtf
(6-6/7)