blob: 5a2223e4532fa99f212b25f1380edf21ed69eef7 [file] [log] [blame]
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001#include <stddef.h>
Zhiqiang Han620b9252021-11-09 14:23:20 +08002#include <unistd.h>
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003#include <stdlib.h>
4#include <pthread.h>
5#include <string.h>
6#include <time.h>
7#include <errno.h>
Zhiqiang Han18f42c82021-08-11 17:13:28 +08008#include <sys/time.h>
Wentao MA361eaac2023-03-21 13:12:28 +08009#include <sys/prctl.h>
Zhiqiang Han18f42c82021-08-11 17:13:28 +080010#include <time.h>
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080011
12#include "dvr_types.h"
13#include "dvr_record.h"
14#include "dvr_crypto.h"
15#include "dvr_playback.h"
16#include "dvr_segment.h"
wentao.ma9009aaa2022-10-25 14:26:33 +080017#include "dvr_utils.h"
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080018
19#include "AmTsPlayer.h"
20
21#include "list.h"
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080022
23#include "dvr_wrapper.h"
24
Wentao MA96f68962022-06-15 19:45:35 +080025#define WRAPPER_LOG_TAG "libdvr-wrapper"
26#define DVR_WRAPPER_DEBUG(...) DVR_LOG_PRINT(LOG_LV_DEBUG, WRAPPER_LOG_TAG, __VA_ARGS__)
27#define DVR_WRAPPER_INFO(...) DVR_LOG_PRINT(LOG_LV_INFO, WRAPPER_LOG_TAG, __VA_ARGS__)
28#define DVR_WRAPPER_WARN(...) DVR_LOG_PRINT(LOG_LV_WARN, WRAPPER_LOG_TAG, __VA_ARGS__)
29#define DVR_WRAPPER_ERROR(...) DVR_LOG_PRINT(LOG_LV_ERROR, WRAPPER_LOG_TAG, __VA_ARGS__)
30#define DVR_WRAPPER_FATAL(...) DVR_LOG_PRINT(LOG_LV_FATAL, WRAPPER_LOG_TAG, __VA_ARGS__)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080031
32/*duration of data to resume if paused with EVT_REACHED_END in timeshifting*/
hualing chen2932d372020-04-29 13:44:00 +080033#define TIMESHIFT_DATA_DURATION_TO_RESUME (600)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080034/*a tolerant gap*/
35#define DVR_PLAYBACK_END_GAP (1000)
36
Wentao MA96f68962022-06-15 19:45:35 +080037int g_dvr_log_level = LOG_LV_DEFAULT;
38
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080039enum {
40 W_REC = 1,
41 W_PLAYBACK = 2,
42};
43
44enum {
45 U_PIDS = 0x01,
46 U_STAT = 0x02,
47 U_ALL = U_PIDS | U_STAT,
48};
49
50typedef struct {
Gong Kefdb31922022-06-17 17:11:16 +080051 pthread_mutex_t lock;
52 pthread_cond_t cond;
53 int inited;
54 int locked;
55} DVR_WrapperMutex_t;
56
57static void
58wrapper_mutex_init (DVR_WrapperMutex_t *lock)
59{
60 pthread_condattr_t cattr;
61
Zhiqiang Han2259da32022-07-07 15:52:58 +080062 if (lock->inited)
Gong Kefdb31922022-06-17 17:11:16 +080063 return;
64
65 pthread_mutex_init(&lock->lock, NULL);
66
67 pthread_condattr_init(&cattr);
68 pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
69 pthread_cond_init(&lock->cond, &cattr);
70 pthread_condattr_destroy(&cattr);
71
wentao.maa22bc852022-10-13 12:18:06 +080072 // It is not necessary to protect code block below with
73 // DVR_WrapperMutex_t.lock, so the following annotation
wentao.mafd5283f2022-10-14 09:51:13 +080074 // is given to suppress related Coverity complaint.
wentao.maa22bc852022-10-13 12:18:06 +080075 // coverity[missing_lock]
Gong Kefdb31922022-06-17 17:11:16 +080076 lock->locked = 0;
77 lock->inited = 1;
78}
79
80static int
81wrapper_mutex_lock (DVR_WrapperMutex_t *lock)
82{
83 pthread_mutex_lock(&lock->lock);
wentao.maa22bc852022-10-13 12:18:06 +080084 // This couldn't be a infinite loop as Coverity reported.
85 // Loop can finish when another thread calls wrapper_mutex_unlock.
86 // coverity[loop_condition]
Gong Kefdb31922022-06-17 17:11:16 +080087 while (lock->locked) {
88 pthread_cond_wait(&lock->cond, &lock->lock);
89 }
90 lock->locked = 1;
91 pthread_mutex_unlock(&lock->lock);
92
93 return 0;
94}
95
96static int
97wrapper_mutex_unlock (DVR_WrapperMutex_t *lock)
98{
99 pthread_mutex_lock(&lock->lock);
100 lock->locked = 0;
101 pthread_mutex_unlock(&lock->lock);
102 pthread_cond_signal(&lock->cond);
103
104 return 0;
105}
106
107static int
108wrapper_mutex_timedlock (DVR_WrapperMutex_t *lock, struct timespec *tv)
109{
110 int r = 0;
111
112 pthread_mutex_lock(&lock->lock);
113 if (lock->locked) {
Zhiqiang Han61ceb3a2022-07-04 17:03:52 +0800114 //DVR_WRAPPER_DEBUG("Enter cond_timedwait");
Gong Kefdb31922022-06-17 17:11:16 +0800115 r = pthread_cond_timedwait(&lock->cond, &lock->lock, tv);
Zhiqiang Han61ceb3a2022-07-04 17:03:52 +0800116 //DVR_WRAPPER_DEBUG("Leave cond_timedwait");
Gong Kefdb31922022-06-17 17:11:16 +0800117 }
118 if (r == 0) {
119 if (!lock->locked) {
120 lock->locked = 1;
121 } else {
122 r = ETIMEDOUT;
123 }
124 }
125 pthread_mutex_unlock(&lock->lock);
126
127 return r;
128}
129
130#define WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(expr, lock)\
131 do {\
132 if (!(expr)) {\
133 DVR_INFO("%s-%d failed", __func__, __LINE__);\
134 wrapper_mutex_unlock(lock);\
135 return DVR_FAILURE;\
136 }\
137 } while (0);
138
139
140typedef struct {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800141 /*make lock the 1st item in the structure*/
Gong Kefdb31922022-06-17 17:11:16 +0800142 DVR_WrapperMutex_t wrapper_lock;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800143
144 /*rec or play*/
145 int type;
146
147 /*valid if (sn != 0)*/
148 unsigned long sn;
149 unsigned long sn_linked;
150
151 struct list_head segments; /**<head-add list*/
152 uint64_t current_segment_id; /**<id of the current segment*/
153
154 union {
155 struct {
156 DVR_WrapperRecordOpenParams_t param_open;
157 DVR_RecordStartParams_t param_start;
158 DVR_RecordStartParams_t param_update;
159 DVR_RecordHandle_t recorder;
160 DVR_RecordEventFunction_t event_fn;
161 void *event_userdata;
162
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800163 /*total status = seg_status + status + obsolete*/
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800164 DVR_RecordStatus_t seg_status; /**<status of current segment*/
165 DVR_WrapperRecordStatus_t status; /**<status of remaining segments*/
166 uint64_t next_segment_id;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800167
168 DVR_WrapperInfo_t obsolete; /**<data obsolete due to the max limit*/
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800169 } record;
170
171 struct {
172 DVR_WrapperPlaybackOpenParams_t param_open;
173 DVR_PlaybackHandle_t player;
174 DVR_PlaybackEventFunction_t event_fn;
175 void *event_userdata;
176
177 /*total status = seg_status + status*/
178 DVR_PlaybackStatus_t seg_status;
179 DVR_WrapperPlaybackStatus_t status;
180 DVR_PlaybackPids_t pids_req;
181 DVR_PlaybackEvent_t last_event;
Zhiqiang Han3eb75f92020-04-08 10:07:55 +0800182 float speed;
hualing chenb5cd42e2020-04-15 17:03:34 +0800183 DVR_Bool_t reach_end;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800184
185 DVR_WrapperInfo_t obsolete;
hualing chen56c0a162022-01-27 17:01:50 +0800186 DVR_Bool_t tf_full;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800187 } playback;
188 };
189} DVR_WrapperCtx_t;
190
191typedef struct {
192 struct list_head head;
193 unsigned long sn;
194
195 /* rec or playback */
196 int type;
197
198 union {
199 struct {
200 DVR_RecordEvent_t event;
201 DVR_RecordStatus_t status;
202 } record;
203 struct {
204 DVR_PlaybackEvent_t event;
205 DVR_Play_Notify_t status;
206 } playback;
207 };
208} DVR_WrapperEventCtx_t;
209
210typedef struct {
211 pthread_mutex_t lock;
212 char *name;
213 int running;
214 pthread_cond_t cond;
215 pthread_t thread;
216 int type;
217} DVR_WrapperThreadCtx_t;
218
219typedef struct {
220 struct list_head head;
221
222 DVR_RecordSegmentInfo_t seg_info;
223 DVR_PlaybackSegmentInfo_t playback_info;
224} DVR_WrapperPlaybackSegmentInfo_t;
225
226typedef struct {
227 struct list_head head;
228
229 DVR_RecordSegmentInfo_t info;
230} DVR_WrapperRecordSegmentInfo_t;
231
232/* serial num generater */
233static unsigned long sn = 1;
234static pthread_mutex_t sn_lock = PTHREAD_MUTEX_INITIALIZER;
235
236static inline unsigned long get_sn()
237{
hualing chenab0d1262021-09-26 15:22:50 +0800238 unsigned long no = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800239
240 pthread_mutex_lock(&sn_lock);
241 no = sn++;
242 if (!no)
243 no = sn++;
244 pthread_mutex_unlock(&sn_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800245 return no;
246}
247
248/* entity ctx */
249#define DVR_WRAPPER_MAX 10
250
251static DVR_WrapperCtx_t record_list[DVR_WRAPPER_MAX] =
252{
253 [0 ... (DVR_WRAPPER_MAX - 1)] =
254 {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800255 .type = W_REC,
256 }
257};
258
259static DVR_WrapperCtx_t playback_list[DVR_WRAPPER_MAX] =
260{
261 [0 ... (DVR_WRAPPER_MAX - 1)] =
262 {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800263 .type = W_PLAYBACK,
264 }
265};
266
267/* events lists */
268static struct list_head record_evt_list = LIST_HEAD_INIT(record_evt_list);
269static struct list_head playback_evt_list = LIST_HEAD_INIT(playback_evt_list);
270
271static pthread_mutex_t record_evt_list_lock = PTHREAD_MUTEX_INITIALIZER;
272static pthread_mutex_t playback_evt_list_lock = PTHREAD_MUTEX_INITIALIZER;
273
274static DVR_WrapperThreadCtx_t wrapper_thread[2] =
275{
276 [0] =
277 {
278 .lock = PTHREAD_MUTEX_INITIALIZER,
279 .running = 0,
280 .name = "record",
281 .type = W_REC,
282 },
283 [1] =
284 {
285 .lock = PTHREAD_MUTEX_INITIALIZER,
286 .running = 0,
287 .name = "playback",
288 .type = W_PLAYBACK,
289 },
290};
291
292/*now only support one timeshift now*/
293static unsigned long sn_timeshift_record;
294static unsigned long sn_timeshift_playback;
295
296static void *wrapper_task(void *arg);
297static inline int process_handleEvents(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx);
298
299static DVR_Result_t wrapper_record_event_handler(DVR_RecordEvent_t event, void *params, void *userdata);
300static DVR_Result_t wrapper_playback_event_handler(DVR_PlaybackEvent_t event, void *params, void *userdata);
301
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800302static int process_generateRecordStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordStatus_t *status);
303static int process_generatePlaybackStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperPlaybackStatus_t *status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800304
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800305static int get_timespec_timeout(int timeout, struct timespec *ts)
306{
307 struct timespec ots;
308 int left, diff;
309
310 clock_gettime(CLOCK_MONOTONIC, &ots);
311
312 ts->tv_sec = ots.tv_sec + timeout / 1000;
313 ts->tv_nsec = ots.tv_nsec;
314
315 left = timeout % 1000;
316 left *= 1000000;
317 diff = 1000000000 - ots.tv_nsec;
318
319 if (diff <= left) {
320 ts->tv_sec++;
321 ts->tv_nsec = left-diff;
322 } else {
323 ts->tv_nsec += left;
324 }
325
326 return 0;
327}
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800328
329static DVR_WrapperEventCtx_t *ctx_getEvent(struct list_head *list, pthread_mutex_t *list_lock)
330{
Wentao MA270dc0f2022-08-23 13:17:26 +0800331 DVR_WrapperEventCtx_t *p_evt;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800332
333 pthread_mutex_lock(list_lock);
334 if (list_empty(list))
Wentao MA270dc0f2022-08-23 13:17:26 +0800335 p_evt = NULL;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800336 else {
Wentao MA270dc0f2022-08-23 13:17:26 +0800337 p_evt = list_first_entry(list, DVR_WrapperEventCtx_t, head);
338 list_del(&p_evt->head);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800339 }
340 pthread_mutex_unlock(list_lock);
341
Wentao MA270dc0f2022-08-23 13:17:26 +0800342 return p_evt;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800343}
344
345static inline DVR_WrapperEventCtx_t *ctx_getRecordEvent()
346{
347 return ctx_getEvent(&record_evt_list, &record_evt_list_lock);
348}
349
350static inline DVR_WrapperEventCtx_t *ctx_getPlaybackEvent()
351{
352 return ctx_getEvent(&playback_evt_list, &playback_evt_list_lock);
353}
354
355static int ctx_addEvent(struct list_head *list, pthread_mutex_t *lock, DVR_WrapperEventCtx_t *evt)
356{
357 DVR_WrapperEventCtx_t *padd;
358 padd = (DVR_WrapperEventCtx_t *)calloc(1, sizeof(DVR_WrapperEventCtx_t));
359 DVR_RETURN_IF_FALSE(padd);
360
361 *padd = *evt;
362 pthread_mutex_lock(lock);
wentao.maa22bc852022-10-13 12:18:06 +0800363 list_add_tail(padd, list);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800364 pthread_mutex_unlock(lock);
365 return DVR_SUCCESS;
366}
367
368static inline void ctx_freeEvent(DVR_WrapperEventCtx_t *evt)
369{
370 free(evt);
371}
372
373/*useless*/
374static void ctx_cleanOutdatedEvents(struct list_head *evt_list,
375 pthread_mutex_t *evt_list_lock,
376 DVR_WrapperCtx_t *list)
377{
Wentao MA270dc0f2022-08-23 13:17:26 +0800378 DVR_WrapperEventCtx_t *p_evt, *p_evt_tmp;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800379 unsigned long sns[DVR_WRAPPER_MAX];
380 int cnt = 0;
381 int i;
382 int found = 0;
383
384 /*copy all valid sns*/
385 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
386 sns[cnt] = list[i].sn;
387 if (!sns[cnt])
388 cnt++;
389 }
390
391 /*free evts that not belong to any valid sns*/
392 pthread_mutex_lock(evt_list_lock);
Wentao MA270dc0f2022-08-23 13:17:26 +0800393 list_for_each_entry_safe(p_evt, p_evt_tmp, evt_list, head) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800394 for (i = 0; i < cnt; i++) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800395 if (p_evt->sn == sns[i]) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800396 found = 1;
397 break;
398 }
399 }
400 if (!found) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800401 list_del(&p_evt->head);
402 ctx_freeEvent(p_evt);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800403 }
404 }
405 pthread_mutex_unlock(evt_list_lock);
406}
407
408static inline void ctx_cleanOutdatedRecordEvents()
409{
410 ctx_cleanOutdatedEvents(&record_evt_list, &record_evt_list_lock, record_list);
411}
412
413static inline void ctx_cleanOutdatedPlaybackEvents()
414{
415 ctx_cleanOutdatedEvents(&playback_evt_list, &playback_evt_list_lock, playback_list);
416}
417
hualing chenb9b358a2021-08-17 15:06:36 +0800418//check this play is recording file
419//return 0 if not the recording
420//else return record id
421static inline int ctx_isPlay_recording(char *play_location)
422{
423 int i;
424 DVR_WrapperCtx_t *cnt;
425
426 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
427 cnt = &record_list[i];
Wentao MA96f68962022-06-15 19:45:35 +0800428 //DVR_WRAPPER_INFO("[%d]sn[%d]R:[%s]P:[%s] ...\n", i, cnt->sn, cnt->record.param_open.location, play_location);
hualing chenb9b358a2021-08-17 15:06:36 +0800429 if (!strcmp(cnt->record.param_open.location, play_location)) {
Wentao MA96f68962022-06-15 19:45:35 +0800430 DVR_WRAPPER_INFO("[%d]sn[%d]R:[%s]P:[%s] .found..\n", i, cnt->sn, cnt->record.param_open.location, play_location);
hualing chenb9b358a2021-08-17 15:06:36 +0800431 return cnt->sn;
432 }
433 }
Wentao MA270dc0f2022-08-23 13:17:26 +0800434 DVR_WRAPPER_INFO(" not found any play is in recording [%d]", DVR_WRAPPER_MAX);
hualing chenb9b358a2021-08-17 15:06:36 +0800435 return 0;
436}
Wentao MA804bab12022-11-29 10:01:26 +0800437
438// Check if the given record is being played.
439// Return 0 if it is not being played, otherwise return its playback id.
hualing chenb9b358a2021-08-17 15:06:36 +0800440static inline int ctx_isRecord_playing(char *rec_location)
441{
442 int i;
443 DVR_WrapperCtx_t *cnt;
444 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
445 cnt = &playback_list[i];
Wentao MA96f68962022-06-15 19:45:35 +0800446 //DVR_WRAPPER_INFO("[%d]sn[%d]P[%s]R[%s] ...\n", i, cnt->sn, cnt->playback.param_open.location, rec_location);
hualing chenb9b358a2021-08-17 15:06:36 +0800447 if (!strcmp(cnt->playback.param_open.location, rec_location)) {
Wentao MA804bab12022-11-29 10:01:26 +0800448 DVR_WRAPPER_DEBUG("[%d]sn[%d]P[%s]R[%s] ..found.",
449 i, cnt->sn, cnt->playback.param_open.location, rec_location);
hualing chenb9b358a2021-08-17 15:06:36 +0800450 return cnt->sn;
451 }
452 }
hualing chenb9b358a2021-08-17 15:06:36 +0800453 return 0;
454}
455
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800456static inline DVR_WrapperCtx_t *ctx_get(unsigned long sn, DVR_WrapperCtx_t *list)
457{
458 int i;
459 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
Gong Kefdb31922022-06-17 17:11:16 +0800460 if (list[i].sn == sn) {
461 wrapper_mutex_init(&list[i].wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800462 return &list[i];
Gong Kefdb31922022-06-17 17:11:16 +0800463 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800464 }
465 return NULL;
466}
467
468static inline void ctx_reset(DVR_WrapperCtx_t *ctx)
469{
470 memset((char *)ctx + offsetof(DVR_WrapperCtx_t, sn),
471 0,
472 sizeof(DVR_WrapperCtx_t) - offsetof(DVR_WrapperCtx_t, sn));
473}
474
475static inline int ctx_valid(DVR_WrapperCtx_t *ctx)
476{
477 return (ctx->sn != 0);
478}
479
480static inline DVR_WrapperCtx_t *ctx_getRecord(unsigned long sn)
481{
482 return ctx_get(sn, record_list);
483}
484
485static inline DVR_WrapperCtx_t *ctx_getPlayback(unsigned long sn)
486{
487 return ctx_get(sn, playback_list);
488}
489
490static int wrapper_requestThread(DVR_WrapperThreadCtx_t *ctx, void *(thread_fn)(void *))
491{
492 pthread_mutex_lock(&ctx->lock);
Zhiqiang Hand59dd162023-10-12 18:15:29 +0800493 ctx->running++;
494 if (ctx->running == 1) {
wentao.maa210e5e2022-10-12 16:10:03 +0800495 pthread_condattr_t attr = {0};
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800496 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
497 pthread_cond_init(&ctx->cond, &attr);
498 pthread_condattr_destroy(&attr);
Wentao MA96f68962022-06-15 19:45:35 +0800499 DVR_WRAPPER_INFO("start wrapper thread(%s) ...\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800500 pthread_create(&ctx->thread, NULL, thread_fn, ctx);
Wentao MA96f68962022-06-15 19:45:35 +0800501 DVR_WRAPPER_INFO("wrapper thread(%s) started\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800502 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800503 pthread_mutex_unlock(&ctx->lock);
504 return 0;
505}
506
507static int wrapper_releaseThread(DVR_WrapperThreadCtx_t *ctx)
508{
509 pthread_mutex_lock(&ctx->lock);
510 ctx->running--;
511 if (!ctx->running) {
512 pthread_cond_broadcast(&ctx->cond);
513 pthread_mutex_unlock(&ctx->lock);
514
Wentao MA96f68962022-06-15 19:45:35 +0800515 DVR_WRAPPER_INFO("stop wrapper thread(%s) ...\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800516 pthread_join(ctx->thread, NULL);
Wentao MA96f68962022-06-15 19:45:35 +0800517 DVR_WRAPPER_INFO("wrapper thread(%s) stopped\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800518
519 pthread_mutex_lock(&ctx->lock);
520 if (!ctx->running) /*protect*/
521 pthread_cond_destroy(&ctx->cond);
522 }
523 pthread_mutex_unlock(&ctx->lock);
524 return 0;
525}
526
527#define WRAPPER_THREAD_RECORD (&wrapper_thread[0])
528#define WRAPPER_THREAD_PLAYBACK (&wrapper_thread[1])
529
530static inline int wrapper_requestThreadFor(DVR_WrapperCtx_t *ctx)
531{
532 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC)?
533 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
534 return wrapper_requestThread(thread_ctx, wrapper_task);
535}
536
537static inline int wrapper_releaseThreadFor(DVR_WrapperCtx_t *ctx)
538{
539 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC)?
540 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
541 return wrapper_releaseThread(thread_ctx);
542}
543
544static inline int wrapper_releaseThreadForType(int type)
545{
546 DVR_WrapperThreadCtx_t *thread_ctx = (type == W_REC)?
547 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
548 return wrapper_releaseThread(thread_ctx);
549}
550
551static inline void wrapper_threadSignal(DVR_WrapperThreadCtx_t *thread_ctx)
552{
553 pthread_cond_signal(&thread_ctx->cond);
554}
555
556static inline int wrapper_threadWait(DVR_WrapperThreadCtx_t *thread_ctx)
557{
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800558 struct timespec rt;
559 get_timespec_timeout(200, &rt);
560 pthread_cond_timedwait(&thread_ctx->cond, &thread_ctx->lock, &rt);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800561 return 0;
562}
563
564static inline void wrapper_threadSignalForType(int type)
565{
566 DVR_WrapperThreadCtx_t *thread_ctx = (type == W_REC) ?
567 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
568 wrapper_threadSignal(thread_ctx);
569}
570
571static inline void wrapper_threadSignalFor(DVR_WrapperCtx_t *ctx)
572{
573 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC) ?
574 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
575 wrapper_threadSignal(thread_ctx);
576}
577
578static inline int wrapper_threadWaitFor(DVR_WrapperCtx_t *ctx)
579{
580 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC) ?
581 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
582 wrapper_threadWait(thread_ctx);
583 return 0;
584}
585
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800586/*return condition, locked if condition == true*/
Gong Kefdb31922022-06-17 17:11:16 +0800587static int wrapper_mutex_lock_if(DVR_WrapperMutex_t *lock, int *condition)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800588{
589 int r2;
590 do {
591 struct timespec rt2;
Gong Kefdb31922022-06-17 17:11:16 +0800592 get_timespec_timeout(10, &rt2);
593 r2 = wrapper_mutex_timedlock(lock, &rt2);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800594 } while (*condition && (r2 == ETIMEDOUT));
595
596 if (!(*condition) && (r2 == 0))
Gong Kefdb31922022-06-17 17:11:16 +0800597 wrapper_mutex_unlock(lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800598
599 return *condition;
600}
601
602static void *wrapper_task(void *arg)
603{
Wentao MA270dc0f2022-08-23 13:17:26 +0800604 DVR_WrapperThreadCtx_t *thread_ctx = (DVR_WrapperThreadCtx_t *)arg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800605 DVR_WrapperEventCtx_t *evt;
606
Wentao MA361eaac2023-03-21 13:12:28 +0800607 prctl(PR_SET_NAME,"DvrWrapper");
608
Wentao MA270dc0f2022-08-23 13:17:26 +0800609 while (thread_ctx->running) {
Zhiqiang Han055aac72023-09-04 16:52:22 +0800610 int ret;
hualing chene3797f02021-01-13 14:53:28 +0800611
Zhiqiang Han055aac72023-09-04 16:52:22 +0800612 evt = (thread_ctx->type == W_REC)? ctx_getRecordEvent() : ctx_getPlaybackEvent();
613 if (!evt) {
614 pthread_mutex_lock(&thread_ctx->lock);
615 ret = wrapper_threadWait(thread_ctx);
616 pthread_mutex_unlock(&thread_ctx->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800617 }
618
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800619 while (evt) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800620 DVR_WrapperCtx_t *ctx = (evt->type == W_REC)?
621 ctx_getRecord(evt->sn) : ctx_getPlayback(evt->sn);
hualing chenbc0aec92021-03-18 14:52:40 +0800622 if (ctx == NULL) {
Wentao MA804bab12022-11-29 10:01:26 +0800623 DVR_WRAPPER_ERROR("Wrapper context is NULL");
hualing chenbc0aec92021-03-18 14:52:40 +0800624 goto processed;
625 }
Wentao MA804bab12022-11-29 10:01:26 +0800626 DVR_WRAPPER_DEBUG("start name(%s) sn(%d) running(%d) type(%d)\n", thread_ctx->name, (int)ctx->sn, thread_ctx->running, thread_ctx->type);
Wentao MA270dc0f2022-08-23 13:17:26 +0800627 if (thread_ctx->running) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800628 /*
629 continue not break,
630 make all events consumed, or mem leak
631 */
Wentao MA270dc0f2022-08-23 13:17:26 +0800632 if (!wrapper_mutex_lock_if(&ctx->wrapper_lock, &thread_ctx->running))
Zhiqiang Hanef61c0a2020-04-13 15:49:24 +0800633 goto processed;
634
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800635 if (ctx_valid(ctx)) {
636 /*double check after lock*/
Zhiqiang Han3b9c9082021-11-10 10:41:09 +0800637 if (evt->sn == ctx->sn) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800638 process_handleEvents(evt, ctx);
Zhiqiang Han3b9c9082021-11-10 10:41:09 +0800639 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800640 }
Zhiqiang Han055aac72023-09-04 16:52:22 +0800641
Gong Kefdb31922022-06-17 17:11:16 +0800642 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800643 }
644
Zhiqiang Hanef61c0a2020-04-13 15:49:24 +0800645processed:
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800646 ctx_freeEvent(evt);
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800647
Wentao MA270dc0f2022-08-23 13:17:26 +0800648 evt = (thread_ctx->type == W_REC)? ctx_getRecordEvent() : ctx_getPlaybackEvent();
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800649 }
650 }
651
Zhiqiang Hand59dd162023-10-12 18:15:29 +0800652 DVR_WRAPPER_DEBUG("wrapper thread(%s) exit, running(%d) type(%d)\n", thread_ctx->name, thread_ctx->running, thread_ctx->type);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800653 return NULL;
654}
655
656static inline int ctx_addRecordEvent(DVR_WrapperEventCtx_t *evt)
657{
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800658 pthread_mutex_lock(&WRAPPER_THREAD_RECORD->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800659 if (ctx_addEvent(&record_evt_list, &record_evt_list_lock, evt) == 0)
660 wrapper_threadSignalForType(evt->type);
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800661 pthread_mutex_unlock(&WRAPPER_THREAD_RECORD->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800662 return 0;
663}
664
665static inline int ctx_addPlaybackEvent(DVR_WrapperEventCtx_t *evt)
666{
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800667 pthread_mutex_lock(&WRAPPER_THREAD_PLAYBACK->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800668 if (ctx_addEvent(&playback_evt_list, &playback_evt_list_lock, evt) == 0)
Zhiqiang Han055aac72023-09-04 16:52:22 +0800669 wrapper_threadSignalForType(evt->type);
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800670 pthread_mutex_unlock(&WRAPPER_THREAD_PLAYBACK->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800671 return 0;
672}
673
674static inline void ctx_freeSegments(DVR_WrapperCtx_t *ctx)
675{
Wentao MA270dc0f2022-08-23 13:17:26 +0800676 DVR_WrapperPlaybackSegmentInfo_t *p_seg, *p_seg_tmp;
677 list_for_each_entry_safe(p_seg, p_seg_tmp, &ctx->segments, head) {
678 list_del(&p_seg->head);
679 free(p_seg);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800680 }
681}
682
Wentao MA270dc0f2022-08-23 13:17:26 +0800683static inline void _updatePlaybackSegment(DVR_WrapperPlaybackSegmentInfo_t *p_seg,
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800684 DVR_RecordSegmentInfo_t *seg_info, int update_flags, DVR_WrapperCtx_t *ctx)
685{
686 (void)ctx;
687 if ((update_flags & U_PIDS) && (update_flags & U_STAT))
Wentao MA270dc0f2022-08-23 13:17:26 +0800688 p_seg->seg_info = *seg_info;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800689 else if (update_flags & U_PIDS) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800690 p_seg->seg_info.nb_pids = seg_info->nb_pids;
691 memcpy(p_seg->seg_info.pids, seg_info->pids, sizeof(p_seg->seg_info.pids));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800692 } else if (update_flags & U_STAT) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800693 p_seg->seg_info.duration = seg_info->duration;
694 p_seg->seg_info.size = seg_info->size;
695 p_seg->seg_info.nb_packets = seg_info->nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800696 }
hualing chen03fd4942021-07-15 15:56:41 +0800697 //update current segment duration on timeshift mode
hualing chenb9b358a2021-08-17 15:06:36 +0800698 if (ctx->playback.param_open.is_timeshift
699 || ctx_isPlay_recording(ctx->playback.param_open.location))
Wentao MA270dc0f2022-08-23 13:17:26 +0800700 dvr_playback_update_duration(ctx->playback.player,p_seg->seg_info.id,p_seg->seg_info.duration);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800701 /*no changes
702 DVR_PlaybackSegmentFlag_t flags;
Wentao MA270dc0f2022-08-23 13:17:26 +0800703 p_seg->playback_info.segment_id = p_seg->seg_info.id;
704 strncpy(p_seg->playback_info.location,
705 ctx->playback.param_open.location, sizeof(p_seg->playback_info.location));
706 p_seg->playback_info.pids = ctx->playback.pids_req;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800707 flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
708 if (ctx->record.param_open.flags | DVR_RECORD_FLAG_SCRAMBLED)
709 flags |= DVR_PLAYBACK_SEGMENT_ENCRYPTED;
Wentao MA270dc0f2022-08-23 13:17:26 +0800710 p_seg->playback_info.flags = flags;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800711 */
712}
713
714static int wrapper_updatePlaybackSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info, int update_flags)
715{
Wentao MA270dc0f2022-08-23 13:17:26 +0800716 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800717
Wentao MA96f68962022-06-15 19:45:35 +0800718 DVR_WRAPPER_INFO("timeshift, update playback segments(wrapper), seg:%lld t/s/p(%ld/%zu/%u)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800719 seg_info->id, seg_info->duration, seg_info->size, seg_info->nb_packets);
720
721 if (list_empty(&ctx->segments)) {
Wentao MA96f68962022-06-15 19:45:35 +0800722 DVR_WRAPPER_INFO("timeshift, update while no segment exists, ignore\n");
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800723 return DVR_SUCCESS;
724 }
725
726 /*normally, the last segment added will be updated*/
Wentao MA270dc0f2022-08-23 13:17:26 +0800727 p_seg =
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800728 list_first_entry(&ctx->segments, DVR_WrapperPlaybackSegmentInfo_t, head);
Wentao MA270dc0f2022-08-23 13:17:26 +0800729 if (p_seg->seg_info.id == seg_info->id) {
730 _updatePlaybackSegment(p_seg, seg_info, update_flags, ctx);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800731 } else {
wentao.mafd5283f2022-10-14 09:51:13 +0800732 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +0800733 // prefetch() here incurring self_assign is used to avoid some compiling
734 // warnings.
735 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +0800736 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
737 if (p_seg->seg_info.id == seg_info->id) {
738 _updatePlaybackSegment(p_seg, seg_info, update_flags, ctx);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800739 break;
740 }
741 }
742 }
743
744 /*need to notify the dvr_playback*/
hualing chenb9b358a2021-08-17 15:06:36 +0800745 if ((ctx->playback.param_open.is_timeshift/*should must be timeshift*/
746 || ctx_isPlay_recording(ctx->playback.param_open.location))
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800747 && ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_END
748 && ctx->playback.seg_status.state == DVR_PLAYBACK_STATE_PAUSE) {
749 if (
750 /*there's $TIMESHIFT_DATA_DURATION_TO_RESUME more of data in the current segment playing*/
751 (ctx->playback.seg_status.segment_id == seg_info->id
Zhiqiang Han9b0b7292023-02-21 17:15:32 +0800752 && (seg_info->duration >= ((time_t)ctx->playback.seg_status.time_cur + TIMESHIFT_DATA_DURATION_TO_RESUME))
753 && ctx->playback.speed != 0.0f)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800754 ||
755 /*or there's a new segment and has $TIMESHIFT_DATA_DURATION_TO_RESUME of data*/
756 (ctx->playback.seg_status.segment_id != seg_info->id
Zhiqiang Han9b0b7292023-02-21 17:15:32 +0800757 && (seg_info->duration >= TIMESHIFT_DATA_DURATION_TO_RESUME)
758 && ctx->playback.speed != 0.0f)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800759 )
760 {
761 int error;
hualing chen36e0dfd2020-05-02 16:33:06 +0800762 //clear end event
Zhiqiang Hanb723cdb2020-05-09 11:10:29 +0800763 if (ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_END)
hualing chen36e0dfd2020-05-02 16:33:06 +0800764 ctx->playback.last_event = DVR_PLAYBACK_EVENT_TRANSITION_OK;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800765
766 error = dvr_playback_resume(ctx->playback.player);
Wentao MA96f68962022-06-15 19:45:35 +0800767 DVR_WRAPPER_INFO("timeshift, resume playback(sn:%ld) (%d) id/dur: rec(%lld/%ld) play(%lld/%u)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800768 ctx->sn, error,
769 seg_info->id, seg_info->duration,
770 ctx->playback.seg_status.segment_id, ctx->playback.seg_status.time_cur);
771 }
772 }
773
774 return DVR_SUCCESS;
775}
776
Wentao MA270dc0f2022-08-23 13:17:26 +0800777static void _updateRecordSegment(DVR_WrapperRecordSegmentInfo_t *p_seg,
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800778 DVR_RecordSegmentInfo_t *seg_info, int update_flags, DVR_WrapperCtx_t *ctx)
779{
780 (void)ctx;
781 if ((update_flags & U_PIDS) && (update_flags & U_STAT))
Wentao MA270dc0f2022-08-23 13:17:26 +0800782 p_seg->info = *seg_info;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800783 else if (update_flags & U_PIDS) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800784 p_seg->info.nb_pids = seg_info->nb_pids;
785 memcpy(p_seg->info.pids, seg_info->pids, sizeof(p_seg->info.pids));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800786 } else if (update_flags & U_STAT) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800787 p_seg->info.duration = seg_info->duration;
788 p_seg->info.size = seg_info->size;
789 p_seg->info.nb_packets = seg_info->nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800790 }
791}
792
793static int wrapper_updateRecordSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info, int update_flags)
794{
Wentao MA270dc0f2022-08-23 13:17:26 +0800795 DVR_WrapperRecordSegmentInfo_t *p_seg = NULL;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800796
797 /*normally, the last segment added will be updated*/
hualing chen266b9502020-04-04 17:39:39 +0800798 if (!list_empty(&ctx->segments)) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800799 p_seg =
hualing chen266b9502020-04-04 17:39:39 +0800800 list_first_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
Wentao MA270dc0f2022-08-23 13:17:26 +0800801 if (p_seg->info.id == seg_info->id) {
802 _updateRecordSegment(p_seg, seg_info, update_flags, ctx);
hualing chen266b9502020-04-04 17:39:39 +0800803 } else {
wentao.mafd5283f2022-10-14 09:51:13 +0800804 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +0800805 // prefetch() here incurring self_assign is used to avoid some compiling
806 // warnings.
807 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +0800808 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
809 if (p_seg->info.id == seg_info->id) {
810 _updateRecordSegment(p_seg, seg_info, update_flags, ctx);
hualing chen266b9502020-04-04 17:39:39 +0800811 break;
812 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800813 }
814 }
815 }
816
817 /*timeshift, update the segment for playback*/
818 /*
819 the playback should grab the segment info other than the id,
820 and the id will be updated by each segment-add during the recording
821 */
822 /*
823 the playback paused if no data been checked from recording,
824 should resume the player later when there's more data
825 */
hualing chenb9b358a2021-08-17 15:06:36 +0800826 int sn = 0;
827 if (ctx->record.param_open.is_timeshift ||
828 (sn = ctx_isRecord_playing(ctx->record.param_open.location))) {
829 DVR_WrapperCtx_t *ctx_playback;
830 if (ctx->record.param_open.is_timeshift)
831 ctx_playback = ctx_getPlayback(sn_timeshift_playback);
832 else
833 ctx_playback = ctx_getPlayback(sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800834
835 if (ctx_playback) {
Gong Kefdb31922022-06-17 17:11:16 +0800836 wrapper_mutex_lock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800837 if (ctx_valid(ctx_playback)
hualing chenb9b358a2021-08-17 15:06:36 +0800838 && (ctx_playback->sn == sn_timeshift_playback ||
839 ctx_playback->sn == sn)) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800840 wrapper_updatePlaybackSegment(ctx_playback, seg_info, update_flags);
841 }
Gong Kefdb31922022-06-17 17:11:16 +0800842 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800843 }
844 }
845
846 return DVR_SUCCESS;
847}
848
849static int wrapper_addPlaybackSegment(DVR_WrapperCtx_t *ctx,
850 DVR_RecordSegmentInfo_t *seg_info,
851 DVR_PlaybackPids_t *p_pids,
852 DVR_PlaybackSegmentFlag_t flags)
853{
Wentao MA270dc0f2022-08-23 13:17:26 +0800854 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Wentao MA270dc0f2022-08-23 13:17:26 +0800855 p_seg = (DVR_WrapperPlaybackSegmentInfo_t *)calloc(1, sizeof(DVR_WrapperPlaybackSegmentInfo_t));
856 if (!p_seg) {
Wentao MA96f68962022-06-15 19:45:35 +0800857 DVR_WRAPPER_INFO("memory fail\n");
Wentao MAe2a2db92024-08-26 16:21:41 +0800858 return DVR_FAILURE;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800859 }
860
Wentao MA270dc0f2022-08-23 13:17:26 +0800861 /*copy the original segment info*/
862 p_seg->seg_info = *seg_info;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800863 /*generate the segment info used in playback*/
Wentao MA270dc0f2022-08-23 13:17:26 +0800864 p_seg->playback_info.segment_id = p_seg->seg_info.id;
Wentao MAe88ad702022-09-02 10:35:00 +0800865 const int len = strlen(ctx->playback.param_open.location);
866 if (len >= DVR_MAX_LOCATION_SIZE || len <= 0) {
867 DVR_WRAPPER_ERROR("Invalid playback.param_open.location length %d", len);
Wentao MA4d85ff32022-09-23 11:36:18 +0800868 free(p_seg);
Wentao MAe88ad702022-09-02 10:35:00 +0800869 return DVR_FAILURE;
870 }
871 strncpy(p_seg->playback_info.location, ctx->playback.param_open.location, len+1);
Wentao MA270dc0f2022-08-23 13:17:26 +0800872 p_seg->playback_info.pids = *p_pids;
873 p_seg->playback_info.flags = flags;
Wentao MA270dc0f2022-08-23 13:17:26 +0800874 p_seg->playback_info.duration = p_seg->seg_info.duration;
wentao.maa22bc852022-10-13 12:18:06 +0800875 list_add(p_seg, &ctx->segments);
876 DVR_WRAPPER_INFO("start to add segment %lld\n", p_seg->playback_info.segment_id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800877
Wentao MAe2a2db92024-08-26 16:21:41 +0800878 int error = dvr_playback_add_segment(ctx->playback.player, &p_seg->playback_info);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800879 if (error) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800880 DVR_WRAPPER_INFO("fail to add segment %lld (%d)\n", p_seg->playback_info.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800881 } else {
Wentao MA270dc0f2022-08-23 13:17:26 +0800882 ctx->playback.status.info_full.time += p_seg->seg_info.duration;
883 ctx->playback.status.info_full.size += p_seg->seg_info.size;
884 ctx->playback.status.info_full.pkts += p_seg->seg_info.nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800885 }
886
887 return error;
888}
889
890static int wrapper_addRecordSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info)
891{
Wentao MA270dc0f2022-08-23 13:17:26 +0800892 DVR_WrapperRecordSegmentInfo_t *p_seg;
Wentao MA16f870e2022-09-09 11:00:22 +0800893 int error = DVR_SUCCESS;
hualing chenab0d1262021-09-26 15:22:50 +0800894 int sn = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800895
Wentao MA270dc0f2022-08-23 13:17:26 +0800896 p_seg = (DVR_WrapperRecordSegmentInfo_t *)calloc(1, sizeof(DVR_WrapperRecordSegmentInfo_t));
897 if (!p_seg) {
Wentao MA16f870e2022-09-09 11:00:22 +0800898 DVR_WRAPPER_ERROR("memory allocation failed");
899 return DVR_FAILURE;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800900 }
Wentao MA270dc0f2022-08-23 13:17:26 +0800901 p_seg->info = *seg_info;
wentao.maa22bc852022-10-13 12:18:06 +0800902 list_add(p_seg, &ctx->segments);
hualing chenab0d1262021-09-26 15:22:50 +0800903
hualing chenb9b358a2021-08-17 15:06:36 +0800904 if (ctx->record.param_open.is_timeshift ||
905 (sn = ctx_isRecord_playing(ctx->record.param_open.location))) {
906
907 DVR_WrapperCtx_t *ctx_playback;
908 if (ctx->record.param_open.is_timeshift)
909 ctx_playback = ctx_getPlayback(sn_timeshift_playback);
910 else
911 ctx_playback = ctx_getPlayback(sn);
912
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800913 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: playback(sn:%ld) add seg\n", ctx->sn, sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800914
915 if (ctx_playback) {
Gong Kefdb31922022-06-17 17:11:16 +0800916 wrapper_mutex_lock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800917 if (ctx_valid(ctx_playback)) {
918 DVR_PlaybackSegmentFlag_t flags;
919
920 /*only if playback has started, the previous segments have been loaded*/
921 if (!list_empty(&ctx_playback->segments)) {
922 flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
Gong Ke2a0ebbe2021-05-25 15:22:50 +0800923 if (ctx->record.param_open.flags & DVR_RECORD_FLAG_SCRAMBLED)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800924 flags |= DVR_PLAYBACK_SEGMENT_ENCRYPTED;
wentao.maa210e5e2022-10-12 16:10:03 +0800925 error = wrapper_addPlaybackSegment(ctx_playback, seg_info, &ctx_playback->playback.pids_req, flags);
926 if (error == DVR_FAILURE) {
927 DVR_WRAPPER_WARN("adding playback segment fails");
928 }
hualing chen451c8f72022-03-09 13:05:52 +0800929 } else {
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800930 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: playback(sn:%ld) list empty\n", ctx->sn, sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800931 }
hualing chenb9b358a2021-08-17 15:06:36 +0800932 } else {
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800933 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: playback(sn:%ld) not valid\n", ctx->sn, sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800934 }
Gong Kefdb31922022-06-17 17:11:16 +0800935 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800936 }
hualing chen451c8f72022-03-09 13:05:52 +0800937 else
938 {
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800939 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: playback(sn:%ld) not valid 2\n", ctx->sn, sn);
940 }
941
942 /*if it is not a timeshift recording, but a playing recording,
943 do not forget to obey the recording rule: link the segment!*/
944 if (!ctx->record.param_open.is_timeshift) {
945 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: update link\n", ctx->sn);
946 dvr_segment_link_op(ctx->record.param_open.location, 1, &seg_info->id, SEGMENT_OP_ADD);
hualing chen451c8f72022-03-09 13:05:52 +0800947 }
Zhiqiang Hane0a1c382021-06-08 11:28:05 +0800948 } else {
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800949 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: update link\n", ctx->sn);
Wentao MAe8ba5172022-08-09 11:18:17 +0800950 dvr_segment_link_op(ctx->record.param_open.location, 1, &seg_info->id, SEGMENT_OP_ADD);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800951 }
952
953 return error;
954}
955
956static int wrapper_removePlaybackSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info)
957{
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800958 int error = -1;
Wentao MA270dc0f2022-08-23 13:17:26 +0800959 DVR_WrapperPlaybackSegmentInfo_t *p_seg = NULL, *p_seg_tmp;
hualing chenb9a1a2c2021-12-31 11:27:59 +0800960 uint32_t off_set = 0;
Wentao MA96f68962022-06-15 19:45:35 +0800961 DVR_WRAPPER_INFO("timeshift, remove playback(sn:%ld) segment(%lld) ...\n", ctx->sn, seg_info->id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800962
Wentao MA270dc0f2022-08-23 13:17:26 +0800963 list_for_each_entry_safe_reverse(p_seg, p_seg_tmp, &ctx->segments, head) {
964 if (p_seg->seg_info.id == seg_info->id) {
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800965
966 if (ctx->current_segment_id == seg_info->id) {
967 DVR_WrapperPlaybackSegmentInfo_t *next_seg;
968
969 /*drive the player out of this will-be-deleted segment*/
Wentao MA270dc0f2022-08-23 13:17:26 +0800970 next_seg = list_prev_entry(p_seg, head);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800971
hualing chenb9a1a2c2021-12-31 11:27:59 +0800972 if (ctx->playback.param_open.vendor == DVR_PLAYBACK_VENDOR_AMAZON)
973 off_set = 10 * 1000;
974 error = dvr_playback_seek(ctx->playback.player, next_seg->seg_info.id, off_set);
Wentao MA96f68962022-06-15 19:45:35 +0800975 DVR_WRAPPER_INFO("timeshift, playback(sn:%ld), seek(seg:%llu 0) from new start (%d)\n", ctx->sn, next_seg->seg_info.id, error);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800976 }
977
978 error = dvr_playback_remove_segment(ctx->playback.player, seg_info->id);
979 if (error) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800980 /*remove playback segment fail*/
Wentao MA96f68962022-06-15 19:45:35 +0800981 DVR_WRAPPER_INFO("timeshift, playback(sn:%ld), failed to remove segment(%llu) (%d)\n", ctx->sn, seg_info->id, error);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800982 }
983
Wentao MA270dc0f2022-08-23 13:17:26 +0800984 list_del(&p_seg->head);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800985
986 /*record the obsolete*/
Wentao MA270dc0f2022-08-23 13:17:26 +0800987 ctx->playback.obsolete.time += p_seg->seg_info.duration;
988 ctx->playback.obsolete.size += p_seg->seg_info.size;
989 ctx->playback.obsolete.pkts += p_seg->seg_info.nb_packets;
Wentao MA96f68962022-06-15 19:45:35 +0800990 DVR_WRAPPER_INFO("timeshift, remove playback(sn:%ld) segment(%lld) ..obs(%d).\n", ctx->sn, seg_info->id, ctx->playback.obsolete.time);
hualing chen03fd4942021-07-15 15:56:41 +0800991 dvr_playback_set_obsolete(ctx->playback.player, ctx->playback.obsolete.time);
Wentao MA270dc0f2022-08-23 13:17:26 +0800992 free(p_seg);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800993 break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800994 }
995 }
996
Wentao MA96f68962022-06-15 19:45:35 +0800997 DVR_WRAPPER_INFO("timeshift, remove playback(sn:%ld) segment(%lld) =(%d)\n", ctx->sn, seg_info->id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800998
999 return error;
1000}
1001
1002static int wrapper_removeRecordSegment(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordSegmentInfo_t *seg_info)
1003{
1004 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08001005 DVR_WrapperRecordSegmentInfo_t *p_seg, *p_seg_tmp;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001006
Wentao MAf4072032022-06-30 13:50:45 +08001007 DVR_WRAPPER_INFO("calling %s on record(sn:%ld) segment(%lld) ...",
1008 __func__, ctx->sn, seg_info->info.id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001009
1010 /*if timeshifting, notify the playback first, then deal with record*/
1011 if (ctx->record.param_open.is_timeshift) {
1012 DVR_WrapperCtx_t *ctx_playback = ctx_getPlayback(sn_timeshift_playback);
1013
1014 if (ctx_playback) {
Gong Kefdb31922022-06-17 17:11:16 +08001015 wrapper_mutex_lock(&ctx_playback->wrapper_lock);
hualing chen56c0a162022-01-27 17:01:50 +08001016 if (ctx_playback->current_segment_id == seg_info->info.id && ctx_playback->playback.speed == 100.0f) {
1017 ctx_playback->playback.tf_full = DVR_TRUE;
Wentao MAf4072032022-06-30 13:50:45 +08001018 DVR_WRAPPER_INFO("%s, cannot remove record(sn:%ld) segment(%lld) for it is being"
1019 " played on segment(%lld) at speed %f.", __func__, ctx->sn, seg_info->info.id,
1020 ctx_playback->current_segment_id, ctx_playback->playback.speed);
Gong Kefdb31922022-06-17 17:11:16 +08001021 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
hualing chen56c0a162022-01-27 17:01:50 +08001022 return DVR_SUCCESS;
1023 } else {
Wentao MAf4072032022-06-30 13:50:45 +08001024 DVR_WRAPPER_INFO("%s, removing record(sn:%ld) segment(%lld) which is being played "
1025 "on segment (%lld) at speed (%f).", __func__, ctx->sn, seg_info->info.id,
1026 ctx_playback->current_segment_id,ctx_playback->playback.speed);
hualing chen56c0a162022-01-27 17:01:50 +08001027 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001028 if (ctx_valid(ctx_playback)
1029 && ctx_playback->sn == sn_timeshift_playback
1030 && !list_empty(&ctx_playback->segments)) {
1031 error = wrapper_removePlaybackSegment(ctx_playback, &seg_info->info);
Wentao MA07d3d742022-09-06 09:58:05 +08001032 if (error != DVR_SUCCESS) {
1033 DVR_WRAPPER_ERROR("wrapper_removePlaybackSegment failed with return value %d",error);
1034 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001035 }
hualing chen56c0a162022-01-27 17:01:50 +08001036 ctx_playback->playback.tf_full = DVR_FALSE;
Gong Kefdb31922022-06-17 17:11:16 +08001037 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001038 }
1039 }
1040
Zhiqiang Hanbc3019b2022-03-21 11:31:21 +08001041 uint64_t id = seg_info->info.id;
1042
Wentao MA270dc0f2022-08-23 13:17:26 +08001043 list_for_each_entry_safe_reverse(p_seg, p_seg_tmp, &ctx->segments, head) {
1044 if (p_seg->info.id == id) {
1045 list_del(&p_seg->head);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001046
1047 /*record the obsolete*/
Wentao MA270dc0f2022-08-23 13:17:26 +08001048 ctx->record.obsolete.time += p_seg->info.duration;
1049 ctx->record.obsolete.size += p_seg->info.size;
1050 ctx->record.obsolete.pkts += p_seg->info.nb_packets;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001051
Wentao MA270dc0f2022-08-23 13:17:26 +08001052 free(p_seg);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001053 break;
1054 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001055 }
1056
Zhiqiang Hanbc3019b2022-03-21 11:31:21 +08001057 error = dvr_segment_delete(ctx->record.param_open.location, id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001058
Wentao MAf4072032022-06-30 13:50:45 +08001059 DVR_WRAPPER_INFO("%s, removed record(sn:%ld) segment(%lld), ret=(%d)\n",
1060 __func__, ctx->sn, id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001061
1062 return error;
1063}
1064
1065int dvr_wrapper_open_record (DVR_WrapperRecord_t *rec, DVR_WrapperRecordOpenParams_t *params)
1066{
1067 int error;
1068 DVR_WrapperCtx_t *ctx;
1069 DVR_RecordOpenParams_t open_param;
1070
1071 DVR_RETURN_IF_FALSE(rec);
1072 DVR_RETURN_IF_FALSE(params);
1073
1074 /*get a free ctx*/
1075 ctx = ctx_getRecord(0);
1076 DVR_RETURN_IF_FALSE(ctx);
1077
Gong Kefdb31922022-06-17 17:11:16 +08001078 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001079
Wentao MA9a164002022-08-29 11:20:24 +08001080 DVR_WRAPPER_INFO("open record(dmx:%d) .is_tf(%d)..time (%ld)ms max size(%lld)byte seg size(%lld)byte\n",
hualing chen51652f02020-12-29 16:59:31 +08001081 params->dmx_dev_id, params->is_timeshift, params->max_time, params->max_size, params->segment_size);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001082
1083 ctx_reset(ctx);
1084
1085 ctx->record.param_open = *params;
1086 ctx->record.event_fn = params->event_fn;
1087 ctx->record.event_userdata = params->event_userdata;
Wentao MA2394fa82022-06-10 14:46:47 +08001088
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001089 INIT_LIST_HEAD(&ctx->segments);
1090 ctx->sn = get_sn();
1091
1092 wrapper_requestThreadFor(ctx);
1093
hualing chen266b9502020-04-04 17:39:39 +08001094 memset(&open_param, 0, sizeof(DVR_RecordOpenParams_t));
Yahui Hance15e9c2020-12-08 18:08:32 +08001095 open_param.fend_dev_id = params->fend_dev_id;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001096 open_param.dmx_dev_id = params->dmx_dev_id;
1097 open_param.data_from_memory = 0;
1098 open_param.flags = params->flags;
Yahui Han15a00f12021-11-15 19:44:39 +08001099 if (params->flush_size) {
1100 open_param.notification_size = params->flush_size;
1101 } else {
1102 open_param.notification_size = 64*1024;
1103 }
hualing chen002e5b92022-02-23 17:51:21 +08001104 open_param.notification_time = 400;//ms
Zhiqiang Han31505452020-05-06 15:08:10 +08001105 open_param.flush_size = params->flush_size;
hualing chen03fd4942021-07-15 15:56:41 +08001106 open_param.ringbuf_size = params->ringbuf_size;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001107 open_param.event_fn = wrapper_record_event_handler;
1108 open_param.event_userdata = (void*)ctx->sn;
Yahui Han1fbf3292021-11-08 18:17:19 +08001109 if (params->keylen) {
1110 open_param.clearkey = params->clearkey;
1111 open_param.cleariv = params->cleariv;
1112 open_param.keylen = params->keylen;
1113 }
wentao.ma35a69d42022-03-10 18:08:40 +08001114 open_param.force_sysclock = params->force_sysclock;
Wentao MAeeffdb02022-06-27 16:34:35 +08001115 open_param.guarded_segment_size = params->segment_size/2*3;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001116
1117 error = dvr_record_open(&ctx->record.recorder, &open_param);
1118 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001119 DVR_WRAPPER_INFO("record(dmx:%d) open fail(error:%d).\n", params->dmx_dev_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001120 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001121 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001122 wrapper_releaseThreadForType(ctx->type);
1123 return DVR_FAILURE;
1124 }
1125 if (params->is_timeshift)
1126 sn_timeshift_record = ctx->sn;
1127
Wentao MA96f68962022-06-15 19:45:35 +08001128 DVR_WRAPPER_INFO("record(dmx:%d) openned ok(sn:%ld).\n", params->dmx_dev_id, ctx->sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001129
Yahui Han1fbf3292021-11-08 18:17:19 +08001130 if (params->crypto_fn) {
1131 error = dvr_record_set_encrypt_callback(ctx->record.recorder, params->crypto_fn, params->crypto_data);
1132 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001133 DVR_WRAPPER_INFO("record(dmx:%d) set encrypt callback fail(error:%d).\n", params->dmx_dev_id, error);
Yahui Han1fbf3292021-11-08 18:17:19 +08001134 }
hualing chen266b9502020-04-04 17:39:39 +08001135 }
1136
Gong Kefdb31922022-06-17 17:11:16 +08001137 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001138
1139 *rec = (DVR_WrapperRecord_t)ctx->sn;
1140 return DVR_SUCCESS;
1141}
1142
1143int dvr_wrapper_close_record (DVR_WrapperRecord_t rec)
1144{
1145 DVR_WrapperCtx_t *ctx;
1146 DVR_RecordSegmentInfo_t seg_info;
1147 int error;
1148
1149 DVR_RETURN_IF_FALSE(rec);
1150
1151 ctx = ctx_getRecord((unsigned long)rec);
1152 DVR_RETURN_IF_FALSE(ctx);
1153
Gong Kefdb31922022-06-17 17:11:16 +08001154 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001155 DVR_WRAPPER_INFO("close record(sn:%ld)\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001156 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001157
1158 memset(&seg_info, 0, sizeof(seg_info));
wentao.maa210e5e2022-10-12 16:10:03 +08001159 dvr_record_stop_segment(ctx->record.recorder, &seg_info);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001160
1161 error = dvr_record_close(ctx->record.recorder);
1162
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001163 if (ctx->record.param_open.is_timeshift)
1164 sn_timeshift_record = 0;
1165
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001166 ctx_freeSegments(ctx);
1167
Wentao MA96f68962022-06-15 19:45:35 +08001168 DVR_WRAPPER_INFO("record(sn:%ld) closed = (%d).\n", ctx->sn, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001169 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001170 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001171
1172 wrapper_releaseThreadForType(ctx->type);
1173
1174 return error;
1175}
1176
1177int dvr_wrapper_start_record (DVR_WrapperRecord_t rec, DVR_WrapperRecordStartParams_t *params)
1178{
1179 DVR_WrapperCtx_t *ctx;
1180 DVR_RecordStartParams_t *start_param;
1181 int i;
1182 int error;
1183
1184 DVR_RETURN_IF_FALSE(rec);
1185 DVR_RETURN_IF_FALSE(params);
1186
1187 ctx = ctx_getRecord((unsigned long)rec);
1188 DVR_RETURN_IF_FALSE(ctx);
1189
Gong Kefdb31922022-06-17 17:11:16 +08001190 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08001191 DVR_WRAPPER_INFO("libdvr_api, start_record (sn:%ld) location:%s, save:%d",
1192 ctx->sn, ctx->record.param_open.location, params->save_rec_file);
Gong Kefdb31922022-06-17 17:11:16 +08001193 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001194
1195 start_param = &ctx->record.param_start;
1196 memset(start_param, 0, sizeof(*start_param));
Wentao MAe88ad702022-09-02 10:35:00 +08001197 const int len = strlen(ctx->record.param_open.location);
1198 if (len >= DVR_MAX_LOCATION_SIZE || len <= 0) {
1199 DVR_WRAPPER_ERROR("Invalid record.param_open.location length %d",len);
1200 pthread_mutex_unlock(&ctx->wrapper_lock);
1201 return DVR_FAILURE;
1202 }
1203 strncpy(start_param->location, ctx->record.param_open.location, len+1);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001204 start_param->segment.nb_pids = params->pids_info.nb_pids;
1205 for (i = 0; i < params->pids_info.nb_pids; i++) {
1206 start_param->segment.pids[i] = params->pids_info.pids[i];
1207 start_param->segment.pid_action[i] = DVR_RECORD_PID_CREATE;
1208 }
Zhiqiang Han89c77972022-12-08 12:16:39 +08001209
hualing chena5f03222021-12-02 11:22:35 +08001210 if (params->save_rec_file == 0)//default is not save
1211 dvr_segment_del_by_location(start_param->location);
Zhiqiang Han89c77972022-12-08 12:16:39 +08001212
1213 //wait for the file status to stabilize before set the new segment id
1214 uint64_t new_segment_id = 0;
Zhiqiang Han02e890c2023-04-25 14:55:02 +08001215
1216 if (params->save_rec_file != 0) {
Zhiqiang Han89c77972022-12-08 12:16:39 +08001217 uint32_t segment_nb = 0;
1218 uint64_t *p_segment_ids = NULL;
1219 error = dvr_segment_get_list(ctx->record.param_open.location, &segment_nb, &p_segment_ids);
1220 if (error == DVR_SUCCESS && segment_nb>0) {
1221 // Tainted data issue originating from fgets seem false positive, so we
1222 // just suppress it here.
1223 // coverity[tainted_data]
1224 new_segment_id = p_segment_ids[segment_nb-1]+1;
1225 }
1226 if (p_segment_ids != NULL) {
1227 free(p_segment_ids);
1228 }
Zhiqiang Han89c77972022-12-08 12:16:39 +08001229 }
Zhiqiang Han02e890c2023-04-25 14:55:02 +08001230 DVR_WRAPPER_DEBUG("new_segment_id:%lld\n", new_segment_id);
1231
Zhiqiang Han89c77972022-12-08 12:16:39 +08001232 ctx->record.next_segment_id = new_segment_id;
1233 ctx->current_segment_id = new_segment_id;
1234
1235 start_param->segment.segment_id = ctx->record.next_segment_id++;
1236
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001237 {
1238 /*sync to update for further use*/
1239 DVR_RecordStartParams_t *update_param;
1240 update_param = &ctx->record.param_update;
1241 memcpy(update_param, start_param, sizeof(*update_param));
1242 for (i = 0; i < update_param->segment.nb_pids; i++)
1243 update_param->segment.pid_action[i] = DVR_RECORD_PID_KEEP;
1244 }
1245
1246 error = dvr_record_start_segment(ctx->record.recorder, start_param);
1247 {
1248 DVR_RecordSegmentInfo_t new_seg_info =
1249 { .id = start_param->segment.segment_id, };
1250 wrapper_addRecordSegment(ctx, &new_seg_info);
1251 }
1252
Wentao MA96f68962022-06-15 19:45:35 +08001253 DVR_WRAPPER_INFO("record(sn:%ld) started = (%d)\n", ctx->sn, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001254
Gong Kefdb31922022-06-17 17:11:16 +08001255 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001256
1257 return error;
1258}
1259
1260int dvr_wrapper_stop_record (DVR_WrapperRecord_t rec)
1261{
1262 DVR_WrapperCtx_t *ctx;
1263 DVR_RecordSegmentInfo_t seg_info;
1264 int error;
1265
1266 DVR_RETURN_IF_FALSE(rec);
1267
1268 ctx = ctx_getRecord((unsigned long)rec);
1269 DVR_RETURN_IF_FALSE(ctx);
1270
Gong Kefdb31922022-06-17 17:11:16 +08001271 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08001272 DVR_WRAPPER_INFO("libdvr_api, stop_record (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001273 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001274
1275 memset(&seg_info, 0, sizeof(seg_info));
1276 error = dvr_record_stop_segment(ctx->record.recorder, &seg_info);
1277 wrapper_updateRecordSegment(ctx, &seg_info, U_ALL);
1278
Wentao MAd71e2062023-02-15 10:10:49 +08001279 ctx_freeSegments(ctx);
1280
Wentao MA96f68962022-06-15 19:45:35 +08001281 DVR_WRAPPER_INFO("record(sn:%ld) stopped = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001282 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001283
1284 return error;
1285}
1286
hualing chen03fd4942021-07-15 15:56:41 +08001287int dvr_wrapper_pause_record (DVR_WrapperRecord_t rec)
1288{
1289 DVR_WrapperCtx_t *ctx;
1290 int error;
1291
1292 DVR_RETURN_IF_FALSE(rec);
1293
1294 ctx = ctx_getRecord((unsigned long)rec);
1295 DVR_RETURN_IF_FALSE(ctx);
1296
Gong Kefdb31922022-06-17 17:11:16 +08001297 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08001298 DVR_WRAPPER_INFO("libdvr_api, pause_record (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001299 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001300
1301 error = dvr_record_pause(ctx->record.recorder);
1302
Wentao MA96f68962022-06-15 19:45:35 +08001303 DVR_WRAPPER_INFO("record(sn:%ld) pauseed = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001304 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001305
1306 return error;
1307}
1308
1309int dvr_wrapper_resume_record (DVR_WrapperRecord_t rec)
1310{
1311 DVR_WrapperCtx_t *ctx;
1312 int error;
1313
1314 DVR_RETURN_IF_FALSE(rec);
1315
1316 ctx = ctx_getRecord((unsigned long)rec);
1317 DVR_RETURN_IF_FALSE(ctx);
1318
Gong Kefdb31922022-06-17 17:11:16 +08001319 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08001320 DVR_WRAPPER_INFO("libdvr_api, resume_record (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001321 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001322
1323 error = dvr_record_resume(ctx->record.recorder);
1324
Wentao MA96f68962022-06-15 19:45:35 +08001325 DVR_WRAPPER_INFO("record(sn:%ld) resumed = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001326 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001327
1328 return error;
1329}
1330
Wentao MAcdea4762022-04-26 13:28:56 +08001331/* Return true if arr1 contains all elements in arr2 */
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001332static DVR_Bool_t pids_test_include(
1333 DVR_StreamPid_t* arr1, DVR_RecordPidAction_t *act1, int size1,
1334 DVR_StreamPid_t* arr2, DVR_RecordPidAction_t *act2, int size2)
wentao.maa69578c2022-04-07 09:27:39 +08001335{
Wentao MAcdea4762022-04-26 13:28:56 +08001336 DVR_Bool_t ret = DVR_TRUE;
1337 for (int i=0;i<size2;i++)
1338 { // iterate all elements in arr2 to check if they exist in arr1
1339 DVR_Bool_t found=DVR_FALSE;
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001340
1341 if (act2[i] == DVR_RECORD_PID_CLOSE)
1342 continue;
1343
Wentao MAcdea4762022-04-26 13:28:56 +08001344 for (int j=0;j<size1;j++)
wentao.maa69578c2022-04-07 09:27:39 +08001345 {
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001346 if (act1[j] != DVR_RECORD_PID_CLOSE
1347 && arr2[i].pid == arr1[j].pid)
wentao.maa69578c2022-04-07 09:27:39 +08001348 {
1349 found=DVR_TRUE;
1350 break;
1351 }
1352 }
1353 if (found == DVR_FALSE)
1354 {
Wentao MAcdea4762022-04-26 13:28:56 +08001355 ret=DVR_FALSE;
wentao.maa69578c2022-04-07 09:27:39 +08001356 break;
1357 }
1358 }
Wentao MAcdea4762022-04-26 13:28:56 +08001359 return ret;
1360}
1361
1362static DVR_Bool_t pids_equal(const DVR_RecordSegmentStartParams_t* p1,
1363 const DVR_WrapperUpdatePidsParams_t* p2)
1364{
1365 int i=0;
1366 char buf[128]={0};
1367 int cnt=0;
1368 int chars=0;
1369
1370 DVR_RETURN_IF_FALSE(p1 != NULL && p2 != NULL);
1371 DVR_RETURN_IF_FALSE(p1->nb_pids>0 && p2->nb_pids>0);
1372
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001373 DVR_Bool_t cond1 = pids_test_include(p1->pids,p1->pid_action,p1->nb_pids,
1374 p2->pids,p2->pid_action,p2->nb_pids);
1375 DVR_Bool_t cond2 = pids_test_include(p2->pids,p2->pid_action,p2->nb_pids,
1376 p1->pids,p1->pid_action,p1->nb_pids);
Wentao MAcdea4762022-04-26 13:28:56 +08001377 DVR_Bool_t is_equal = (cond1 && cond2);
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001378 int removed;
Wentao MAcdea4762022-04-26 13:28:56 +08001379
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001380 removed = 0;
Wentao MAcdea4762022-04-26 13:28:56 +08001381 for (i=0;i<p1->nb_pids;i++)
1382 {
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001383 if (p1->pid_action[i] == DVR_RECORD_PID_CLOSE) {
1384 removed++;
1385 continue;
1386 }
Wentao MAcdea4762022-04-26 13:28:56 +08001387 chars = snprintf(buf+cnt,sizeof(buf)-cnt,"0x%hx,",p1->pids[i].pid);
1388 if (chars<0)
1389 {
1390 break;
1391 }
1392 cnt += chars;
1393 }
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001394 DVR_INFO("%s nb_pids1:%d, pids1: %s",__func__,p1->nb_pids-removed,buf);
Wentao MAcdea4762022-04-26 13:28:56 +08001395 memset(buf,0,sizeof(buf));
1396
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001397 removed = 0;
Wentao MAcdea4762022-04-26 13:28:56 +08001398 for (i=0,cnt=0;i<p2->nb_pids;i++)
1399 {
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001400 if (p2->pid_action[i] == DVR_RECORD_PID_CLOSE) {
1401 removed++;
1402 continue;
1403 }
Wentao MAcdea4762022-04-26 13:28:56 +08001404 chars = snprintf(buf+cnt,sizeof(buf)-cnt,"0x%hx,",p2->pids[i].pid);
1405 if (chars<0)
1406 {
1407 break;
1408 }
1409 cnt += chars;
1410 }
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001411 DVR_INFO("%s nb_pids2:%d, pids2: %s",__func__,p2->nb_pids-removed,buf);
Wentao MA96f68962022-06-15 19:45:35 +08001412 DVR_INFO("%s is_equal:%d",__func__,is_equal);
wentao.maa69578c2022-04-07 09:27:39 +08001413 return is_equal;
1414}
1415
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001416int dvr_wrapper_update_record_pids (DVR_WrapperRecord_t rec, DVR_WrapperUpdatePidsParams_t *params)
1417{
1418 DVR_WrapperCtx_t *ctx;
1419 DVR_RecordStartParams_t *start_param;
wentao.maa69578c2022-04-07 09:27:39 +08001420 DVR_RecordSegmentInfo_t seg_info;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001421 int i;
1422 int error;
1423
1424 DVR_RETURN_IF_FALSE(rec);
1425 DVR_RETURN_IF_FALSE(params);
1426
1427 ctx = ctx_getRecord((unsigned long)rec);
1428 DVR_RETURN_IF_FALSE(ctx);
1429
Gong Kefdb31922022-06-17 17:11:16 +08001430 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08001431 DVR_WRAPPER_INFO("libdvr_api, update_record (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001432 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001433
1434 start_param = &ctx->record.param_update;
wentao.maa69578c2022-04-07 09:27:39 +08001435 if (pids_equal(&(start_param->segment),params))
1436 {
Gong Kefdb31922022-06-17 17:11:16 +08001437 wrapper_mutex_unlock(&ctx->wrapper_lock);
wentao.maa69578c2022-04-07 09:27:39 +08001438 return DVR_TRUE;
1439 }
1440
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001441 memset(start_param, 0, sizeof(*start_param));
Wentao MAe88ad702022-09-02 10:35:00 +08001442 const int len = strlen(ctx->record.param_open.location);
1443 if (len >= DVR_MAX_LOCATION_SIZE || len <= 0) {
1444 DVR_WRAPPER_ERROR("Invalid record.param_open.location length %d",len);
1445 pthread_mutex_unlock(&ctx->wrapper_lock);
1446 return DVR_FAILURE;
1447 }
1448 strncpy(start_param->location, ctx->record.param_open.location, len+1);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001449 start_param->segment.segment_id = ctx->record.next_segment_id++;
1450 start_param->segment.nb_pids = params->nb_pids;
1451 for (i = 0; i < params->nb_pids; i++) {
1452 start_param->segment.pids[i] = params->pids[i];
1453 start_param->segment.pid_action[i] = params->pid_action[i];
1454 }
1455 error = dvr_record_next_segment(ctx->record.recorder, start_param, &seg_info);
1456 {
1457 DVR_RecordSegmentInfo_t new_seg_info =
1458 { .id = start_param->segment.segment_id, };
1459 wrapper_updateRecordSegment(ctx, &seg_info, U_PIDS);
1460 wrapper_addRecordSegment(ctx, &new_seg_info);
1461 }
1462
Wentao MA96f68962022-06-15 19:45:35 +08001463 DVR_WRAPPER_INFO("record(sn:%ld) updated = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001464 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001465
1466 return error;
1467}
1468
1469int dvr_wrapper_get_record_status(DVR_WrapperRecord_t rec, DVR_WrapperRecordStatus_t *status)
1470{
1471 DVR_WrapperCtx_t *ctx;
1472 DVR_WrapperRecordStatus_t s;
1473 int error;
1474
1475 DVR_RETURN_IF_FALSE(rec);
1476 DVR_RETURN_IF_FALSE(status);
1477
1478 ctx = ctx_getRecord((unsigned long)rec);
1479 DVR_RETURN_IF_FALSE(ctx);
1480
Gong Kefdb31922022-06-17 17:11:16 +08001481 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001482
Wentao MA804bab12022-11-29 10:01:26 +08001483 DVR_WRAPPER_INFO("libdvr_api, get_record_status (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001484 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001485
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001486 error = process_generateRecordStatus(ctx, &s);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001487
Wentao MA96f68962022-06-15 19:45:35 +08001488 DVR_WRAPPER_INFO("record(sn:%ld) state/time/size/pkts(%d/%ld/%lld/%u) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001489 ctx->sn,
1490 s.state,
1491 s.info.time,
1492 s.info.size,
1493 s.info.pkts,
1494 error);
1495
1496 *status = s;
1497
Gong Kefdb31922022-06-17 17:11:16 +08001498 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001499
1500 return error;
1501}
1502
hualing chen4fe3bee2020-10-23 13:58:52 +08001503int dvr_wrapper_record_is_secure_mode(DVR_WrapperRecord_t rec)
1504{
1505 DVR_WrapperCtx_t *ctx;
1506 int error;
1507
1508 DVR_RETURN_IF_FALSE(rec);
1509
1510 ctx = ctx_getRecord((unsigned long)rec);
1511 DVR_RETURN_IF_FALSE(ctx);
1512
Gong Kefdb31922022-06-17 17:11:16 +08001513 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen4fe3bee2020-10-23 13:58:52 +08001514 error = dvr_record_is_secure_mode(ctx->record.recorder);
Gong Kefdb31922022-06-17 17:11:16 +08001515 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen4fe3bee2020-10-23 13:58:52 +08001516 return error;
1517}
1518
hualing chen266b9502020-04-04 17:39:39 +08001519int dvr_wrapper_set_record_secure_buffer (DVR_WrapperRecord_t rec, uint8_t *p_secure_buf, uint32_t len)
1520{
1521 DVR_WrapperCtx_t *ctx;
1522 int error;
1523
1524 DVR_RETURN_IF_FALSE(rec);
1525 DVR_RETURN_IF_FALSE(p_secure_buf);
1526
1527 ctx = ctx_getRecord((unsigned long)rec);
1528 DVR_RETURN_IF_FALSE(ctx);
1529
Gong Kefdb31922022-06-17 17:11:16 +08001530 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001531 error = dvr_record_set_secure_buffer(ctx->record.recorder, p_secure_buf, len);
Gong Kefdb31922022-06-17 17:11:16 +08001532 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001533 return error;
1534}
1535
1536int dvr_wrapper_set_record_decrypt_callback (DVR_WrapperRecord_t rec, DVR_CryptoFunction_t func, void *userdata)
1537{
1538 DVR_WrapperCtx_t *ctx;
1539 int error;
1540
1541 DVR_RETURN_IF_FALSE(rec);
1542 DVR_RETURN_IF_FALSE(func);
1543
1544 ctx = ctx_getRecord((unsigned long)rec);
1545 DVR_RETURN_IF_FALSE(ctx);
1546
Gong Kefdb31922022-06-17 17:11:16 +08001547 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001548 error = dvr_record_set_encrypt_callback(ctx->record.recorder, func, userdata);
Gong Kefdb31922022-06-17 17:11:16 +08001549 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001550 return error;
1551}
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001552
1553
1554int dvr_wrapper_open_playback (DVR_WrapperPlayback_t *playback, DVR_WrapperPlaybackOpenParams_t *params)
1555{
1556 DVR_WrapperCtx_t *ctx;
1557 DVR_PlaybackOpenParams_t open_param;
1558 int error;
1559
1560 DVR_RETURN_IF_FALSE(playback);
1561 DVR_RETURN_IF_FALSE(params);
1562 DVR_RETURN_IF_FALSE(params->playback_handle);
1563
1564 /*get a free ctx*/
1565 ctx = ctx_getPlayback(0);
1566 DVR_RETURN_IF_FALSE(ctx);
1567
Gong Kefdb31922022-06-17 17:11:16 +08001568 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001569
Wentao MA804bab12022-11-29 10:01:26 +08001570 DVR_WRAPPER_INFO("libdvr_api, open_playback (dmx:%d) ..vendor[%d]params->block_size[%d].",
1571 params->dmx_dev_id, params->vendor, params->block_size);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001572
1573 ctx_reset(ctx);
1574
1575 ctx->playback.param_open = *params;
1576 ctx->playback.event_fn = params->event_fn;
1577 ctx->playback.event_userdata = params->event_userdata;
1578 ctx->current_segment_id = 0;
1579 INIT_LIST_HEAD(&ctx->segments);
1580 ctx->sn = get_sn();
1581
1582 wrapper_requestThreadFor(ctx);
1583
hualing chen266b9502020-04-04 17:39:39 +08001584 memset(&open_param, 0, sizeof(DVR_PlaybackOpenParams_t));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001585 open_param.dmx_dev_id = params->dmx_dev_id;
1586 open_param.block_size = params->block_size;
1587 open_param.is_timeshift = params->is_timeshift;
1588 //open_param.notification_size = 10*1024; //not supported
1589 open_param.event_fn = wrapper_playback_event_handler;
1590 open_param.event_userdata = (void*)ctx->sn;
1591 /*open_param.has_pids = 0;*/
hualing chene3797f02021-01-13 14:53:28 +08001592 open_param.is_notify_time = params->is_notify_time;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001593 open_param.player_handle = (am_tsplayer_handle)params->playback_handle;
hualing chen90b3ae62021-03-30 10:49:28 +08001594 open_param.vendor = params->vendor;
1595
Yahui Han1fbf3292021-11-08 18:17:19 +08001596 if (params->keylen) {
1597 open_param.clearkey = params->clearkey;
1598 open_param.cleariv = params->cleariv;
1599 open_param.keylen = params->keylen;
1600 }
shenghui.gengbec6a462023-01-12 15:21:02 +08001601 open_param.control_speed_enable = params->control_speed_enable;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001602
1603 error = dvr_playback_open(&ctx->playback.player, &open_param);
1604 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001605 DVR_WRAPPER_INFO("playback(dmx:%d) openned fail(error:%d).\n", params->dmx_dev_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001606 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001607 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001608 wrapper_releaseThreadForType(ctx->type);
1609 return DVR_FAILURE;
1610 }
1611 if (params->is_timeshift)
1612 sn_timeshift_playback = ctx->sn;
1613
Wentao MA270dc0f2022-08-23 13:17:26 +08001614 DVR_WRAPPER_INFO("playback(dmx:%d) openned ok(sn:%ld).\n", params->dmx_dev_id, ctx->sn);
hualing chen266b9502020-04-04 17:39:39 +08001615 error = dvr_playback_set_decrypt_callback(ctx->playback.player, params->crypto_fn, params->crypto_data);
1616 if (error) {
Wentao MA270dc0f2022-08-23 13:17:26 +08001617 DVR_WRAPPER_INFO("playback set decrypt callback fail(error:%d).\n", error);
hualing chen266b9502020-04-04 17:39:39 +08001618 }
Gong Kefdb31922022-06-17 17:11:16 +08001619 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001620
1621 *playback = (DVR_WrapperPlayback_t)ctx->sn;
1622 return DVR_SUCCESS;
1623}
1624
1625int dvr_wrapper_close_playback (DVR_WrapperPlayback_t playback)
1626{
1627 DVR_WrapperCtx_t *ctx;
1628 int error;
1629
1630 DVR_RETURN_IF_FALSE(playback);
1631
1632 ctx = ctx_getPlayback((unsigned long)playback);
1633 DVR_RETURN_IF_FALSE(ctx);
1634
Gong Kefdb31922022-06-17 17:11:16 +08001635 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08001636 DVR_WRAPPER_INFO("libdvr_api, close_playback (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001637 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001638
1639 if (ctx->playback.param_open.is_timeshift)
1640 sn_timeshift_playback = 0;
1641
1642 /*try stop first*/
wentao.maa210e5e2022-10-12 16:10:03 +08001643 dvr_playback_stop(ctx->playback.player, DVR_TRUE);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001644
1645 {
1646 /*remove all segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08001647 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001648
wentao.mafd5283f2022-10-14 09:51:13 +08001649 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08001650 // prefetch() here incurring self_assign is used to avoid some compiling
1651 // warnings.
1652 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08001653 list_for_each_entry(p_seg, &ctx->segments, head) {
1654 error = dvr_playback_remove_segment(ctx->playback.player, p_seg->playback_info.segment_id);
Wentao MA96f68962022-06-15 19:45:35 +08001655 DVR_WRAPPER_INFO("playback(sn:%ld) remove seg(%lld) (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08001656 ctx->sn, p_seg->playback_info.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001657 }
1658 ctx_freeSegments(ctx);
1659 }
1660
1661 error = dvr_playback_close(ctx->playback.player);
1662
Wentao MA96f68962022-06-15 19:45:35 +08001663 DVR_WRAPPER_INFO("playback(sn:%ld) closed.\n", ctx->sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001664 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001665 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001666
1667 wrapper_releaseThreadForType(ctx->type);
1668
1669 return error;
1670}
1671
1672int dvr_wrapper_start_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackFlag_t flags, DVR_PlaybackPids_t *p_pids)
1673{
1674 DVR_WrapperCtx_t *ctx;
Wentao MA9aa0aa02021-12-23 18:30:17 +08001675 int error=0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001676 uint64_t *p_segment_ids;
1677 uint32_t segment_nb;
1678 uint32_t i;
1679 DVR_RecordSegmentInfo_t seg_info_1st;
Wentao MA9aa0aa02021-12-23 18:30:17 +08001680 int got_1st_seg=0;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001681 DVR_WrapperCtx_t *ctx_record;/*for timeshift*/
hualing chenc110f952021-01-18 11:25:37 +08001682 DVR_Bool_t is_timeshift = DVR_FALSE;
Wentao MAcefc13c2022-10-26 15:47:24 +08001683 DVR_PlaybackSegmentFlag_t seg_flags = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001684
1685 DVR_RETURN_IF_FALSE(playback);
1686 DVR_RETURN_IF_FALSE(p_pids);
1687
hualing chenc110f952021-01-18 11:25:37 +08001688 /*lock the recorder to avoid changing the recording segments*/
1689 ctx_record = ctx_getRecord(sn_timeshift_record);
1690
1691 if (ctx_record) {
Gong Kefdb31922022-06-17 17:11:16 +08001692 wrapper_mutex_lock(&ctx_record->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001693 if (!ctx_valid(ctx_record)
1694 || ctx_record->sn != sn_timeshift_record) {
Wentao MA96f68962022-06-15 19:45:35 +08001695 DVR_WRAPPER_INFO("timeshift, record is not for timeshifting, FATAL error found\n");
Gong Kefdb31922022-06-17 17:11:16 +08001696 wrapper_mutex_unlock(&ctx_record->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001697 is_timeshift = DVR_FALSE;
1698 } else {
1699 is_timeshift = DVR_TRUE;
1700 }
1701 }
1702
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001703 ctx = ctx_getPlayback((unsigned long)playback);
1704 DVR_RETURN_IF_FALSE(ctx);
1705
Gong Kefdb31922022-06-17 17:11:16 +08001706 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001707
Wentao MA804bab12022-11-29 10:01:26 +08001708 DVR_WRAPPER_INFO("libdvr_api, start_playback (sn:%ld) location:%s"
1709 " flags:0x%x v/a/ad/sub/pcr(%d:%d %d:%d %d:%d %d:%d %d)",
1710 ctx->sn,
1711 ctx->playback.param_open.location,
1712 flags,
1713 p_pids->video.pid, p_pids->video.format,
1714 p_pids->audio.pid, p_pids->audio.format,
1715 p_pids->ad.pid, p_pids->ad.format,
1716 p_pids->subtitle.pid, p_pids->subtitle.format,
1717 p_pids->pcr.pid);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001718
Gong Kefdb31922022-06-17 17:11:16 +08001719 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001720
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001721 if (ctx->playback.param_open.is_timeshift) {
1722 /*lock the recorder to avoid changing the recording segments*/
hualing chenc110f952021-01-18 11:25:37 +08001723 if (is_timeshift == DVR_FALSE) {
Wentao MA96f68962022-06-15 19:45:35 +08001724 DVR_WRAPPER_INFO("timeshift, record is not for timeshifting, FATAL error return\n");
Gong Kefdb31922022-06-17 17:11:16 +08001725 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001726 return DVR_FAILURE;
1727 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001728 DVR_WRAPPER_INFO("playback(sn:%ld) record(sn:%ld) locked ok due to timeshift\n",
hualing chenc110f952021-01-18 11:25:37 +08001729 ctx->sn, ctx_record->sn);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001730 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001731 }
1732
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001733 /*obtain all segments in a list*/
1734 segment_nb = 0;
1735 p_segment_ids = NULL;
1736 error = dvr_segment_get_list(ctx->playback.param_open.location, &segment_nb, &p_segment_ids);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001737 if (!error) {
1738 got_1st_seg = 0;
hualing chenb9a02922021-12-14 11:29:47 +08001739 struct list_head info_list; /**< segment list head*/
1740 INIT_LIST_HEAD(&info_list);
1741
Wentao MA96f68962022-06-15 19:45:35 +08001742 DVR_WRAPPER_INFO("get list segment_nb::%d",segment_nb);
hualing chenb9a02922021-12-14 11:29:47 +08001743 //we need free info list buf when we used end.
1744 error = dvr_segment_get_allInfo(ctx->playback.param_open.location, &info_list);
hualing chen926a8ec2021-12-20 20:38:24 +08001745 if (error == DVR_FAILURE) {
hualing chenb9a02922021-12-14 11:29:47 +08001746 error = DVR_FAILURE;
Zhiqiang Handc3bfe52022-07-07 10:48:39 +08001747 DVR_WRAPPER_INFO("fail to get all seg info (location:%s), (error:%d)\n",
1748 ctx->playback.param_open.location, error);
wentao.maf57dd232022-10-08 16:07:29 +08001749 // Tainted data issue originating from fgets seem false positive, so we
1750 // just suppress it here.
1751 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08001752 for (i = 0; i < segment_nb; i++) {
1753 DVR_RecordSegmentInfo_t seg_info;
Wentao MA4d85ff32022-09-23 11:36:18 +08001754 memset((void*)&seg_info,0,sizeof(seg_info));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001755
hualing chenb9a02922021-12-14 11:29:47 +08001756 error = dvr_segment_get_info(ctx->playback.param_open.location, p_segment_ids[i], &seg_info);
1757 if (error) {
1758 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08001759 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chenb9a02922021-12-14 11:29:47 +08001760 ctx->playback.param_open.location, p_segment_ids[i], error);
1761 break;
1762 }
1763 //add check if has audio or video pid. if not exist. not add segment to playback
1764 int ii = 0;
1765 int has_av = 0;
wentao.maf57dd232022-10-08 16:07:29 +08001766 // Tainted data issue originating from fgets seem false positive, so we
1767 // just suppress it here.
1768 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08001769 for (ii = 0; ii < seg_info.nb_pids; ii++) {
1770 int type = (seg_info.pids[ii].type >> 24) & 0x0f;
1771 if (type == DVR_STREAM_TYPE_VIDEO ||
1772 type == DVR_STREAM_TYPE_AUDIO ||
1773 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001774 DVR_WRAPPER_INFO("success to get seg av info \n");
1775 DVR_WRAPPER_INFO("success to get seg av info type[0x%x][%d] [%d][%d][%d]\n",(seg_info.pids[ii].type >> 24)&0x0f,seg_info.pids[ii].pid,
hualing chenb9a02922021-12-14 11:29:47 +08001776 DVR_STREAM_TYPE_VIDEO,
1777 DVR_STREAM_TYPE_AUDIO,
1778 DVR_STREAM_TYPE_AD);
1779 has_av = 1;
1780 //break;
1781 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001782 DVR_WRAPPER_INFO("error to get seg av info type[0x%x][%d] [%d][%d][%d]\n",(seg_info.pids[ii].type >> 24)&0x0f,seg_info.pids[ii].pid,
hualing chenb9a02922021-12-14 11:29:47 +08001783 DVR_STREAM_TYPE_VIDEO,
1784 DVR_STREAM_TYPE_AUDIO,
1785 DVR_STREAM_TYPE_AD);
1786 }
1787 }
1788 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001789 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001790 continue;
1791 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001792 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001793 }
Wentao MAcefc13c2022-10-26 15:47:24 +08001794 seg_flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
1795 error = wrapper_addPlaybackSegment(ctx, &seg_info, p_pids, seg_flags);
wentao.maa210e5e2022-10-12 16:10:03 +08001796 if (error == DVR_FAILURE) {
1797 DVR_WRAPPER_WARN("adding playback segment fails");
hualing chenb9a02922021-12-14 11:29:47 +08001798 break;
wentao.maa210e5e2022-10-12 16:10:03 +08001799 }
hualing chenb9a02922021-12-14 11:29:47 +08001800 /*copy the 1st segment*/
1801 if (got_1st_seg == 0) {
1802 seg_info_1st = seg_info;
1803 got_1st_seg = 1;
1804 }
1805 }
1806 } else {
wentao.maf57dd232022-10-08 16:07:29 +08001807 // Tainted data issue originating from fgets seem false positive, so we
1808 // just suppress it here.
1809 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08001810 for (i = 0; i < segment_nb; i++) {
Wentao MA4d85ff32022-09-23 11:36:18 +08001811 DVR_RecordSegmentInfo_t *p_seg_info;
hualing chenb9a02922021-12-14 11:29:47 +08001812 int found = 0;
wentao.mafd5283f2022-10-14 09:51:13 +08001813 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08001814 // prefetch() here incurring self_assign is used to avoid some compiling
1815 // warnings.
1816 // coverity[self_assign]
Wentao MA4d85ff32022-09-23 11:36:18 +08001817 list_for_each_entry(p_seg_info, &info_list, head)
hualing chenb9a02922021-12-14 11:29:47 +08001818 {
Wentao MA4d85ff32022-09-23 11:36:18 +08001819 if (p_seg_info->id == p_segment_ids[i]) {
hualing chenb9a02922021-12-14 11:29:47 +08001820 found = 1;
Wentao MA96f68962022-06-15 19:45:35 +08001821 DVR_WRAPPER_INFO("get segment info::%d", i);
hualing chenb9a02922021-12-14 11:29:47 +08001822 break;
1823 }
1824 }
1825 if (!found) {
hualing chen8aed9582021-12-24 17:59:56 +08001826 //last info is not found if when recording occured power off.
1827 if (p_segment_ids[i] == segment_nb - 1) {
1828 DVR_RecordSegmentInfo_t seg_info;
Wentao MA4d85ff32022-09-23 11:36:18 +08001829 memset((void*)&seg_info,0,sizeof(seg_info));
hualing chen8aed9582021-12-24 17:59:56 +08001830
1831 error = dvr_segment_get_info(ctx->playback.param_open.location, p_segment_ids[i], &seg_info);
1832 if (error) {
1833 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08001834 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chen8aed9582021-12-24 17:59:56 +08001835 ctx->playback.param_open.location, p_segment_ids[i], error);
1836 break;
1837 }
1838 //
1839 //add check if has audio or video pid. if not exist. not add segment to playback
1840 int ii = 0;
1841 int has_av = 0;
wentao.maf57dd232022-10-08 16:07:29 +08001842 // Tainted data issue originating from fgets seem false positive, so we
1843 // just suppress it here.
1844 // coverity[tainted_data]
hualing chen8aed9582021-12-24 17:59:56 +08001845 for (ii = 0; ii < seg_info.nb_pids; ii++) {
1846 int type = (seg_info.pids[ii].type >> 24) & 0x0f;
1847 if (type == DVR_STREAM_TYPE_VIDEO ||
1848 type == DVR_STREAM_TYPE_AUDIO ||
1849 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001850 DVR_WRAPPER_INFO("success to get seg av info \n");
1851 DVR_WRAPPER_INFO("success to get seg av info type[0x%x][%d] [%d][%d][%d]\n",(seg_info.pids[ii].type >> 24)&0x0f,seg_info.pids[ii].pid,
hualing chen8aed9582021-12-24 17:59:56 +08001852 DVR_STREAM_TYPE_VIDEO,
1853 DVR_STREAM_TYPE_AUDIO,
1854 DVR_STREAM_TYPE_AD);
1855 has_av = 1;
1856 //break;
1857 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001858 DVR_WRAPPER_INFO("error to get seg av info type[0x%x][%d] [%d][%d][%d]\n",(seg_info.pids[ii].type >> 24)&0x0f,seg_info.pids[ii].pid,
hualing chen8aed9582021-12-24 17:59:56 +08001859 DVR_STREAM_TYPE_VIDEO,
1860 DVR_STREAM_TYPE_AUDIO,
1861 DVR_STREAM_TYPE_AD);
1862 }
1863 }
1864 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001865 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chen8aed9582021-12-24 17:59:56 +08001866 continue;
1867 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001868 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chen8aed9582021-12-24 17:59:56 +08001869 }
Wentao MAcefc13c2022-10-26 15:47:24 +08001870 seg_flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
1871 error = wrapper_addPlaybackSegment(ctx, &seg_info, p_pids, seg_flags);
wentao.maa210e5e2022-10-12 16:10:03 +08001872 if (error == DVR_FAILURE) {
1873 DVR_WRAPPER_WARN("adding playback segment fails");
hualing chen8aed9582021-12-24 17:59:56 +08001874 break;
wentao.maa210e5e2022-10-12 16:10:03 +08001875 }
hualing chen8aed9582021-12-24 17:59:56 +08001876 }
hualing chenb9a02922021-12-14 11:29:47 +08001877 continue;
1878 }
1879
1880 //add check if has audio or video pid. if not exist. not add segment to playback
1881 int ii = 0;
1882 int has_av = 0;
Wentao MA4d85ff32022-09-23 11:36:18 +08001883 for (ii = 0; ii < p_seg_info->nb_pids; ii++) {
1884 int type = (p_seg_info->pids[ii].type >> 24) & 0x0f;
hualing chenb9a02922021-12-14 11:29:47 +08001885 if (type == DVR_STREAM_TYPE_VIDEO ||
1886 type == DVR_STREAM_TYPE_AUDIO ||
1887 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001888 DVR_WRAPPER_INFO("success to get seg av info \n");
Wentao MA4d85ff32022-09-23 11:36:18 +08001889 DVR_WRAPPER_INFO("success to get seg av info type[0x%x][%d] [%d][%d][%d]\n",(p_seg_info->pids[ii].type >> 24)&0x0f,p_seg_info->pids[ii].pid,
hualing chenb9a02922021-12-14 11:29:47 +08001890 DVR_STREAM_TYPE_VIDEO,
1891 DVR_STREAM_TYPE_AUDIO,
1892 DVR_STREAM_TYPE_AD);
1893 has_av = 1;
1894 //break;
1895 } else {
Wentao MA4d85ff32022-09-23 11:36:18 +08001896 DVR_WRAPPER_INFO("error to get seg av info type[0x%x][%d] [%d][%d][%d]\n",(p_seg_info->pids[ii].type >> 24)&0x0f,p_seg_info->pids[ii].pid,
hualing chenb9a02922021-12-14 11:29:47 +08001897 DVR_STREAM_TYPE_VIDEO,
1898 DVR_STREAM_TYPE_AUDIO,
1899 DVR_STREAM_TYPE_AD);
1900 }
1901 }
1902 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001903 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001904 continue;
1905 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001906 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001907 }
Wentao MAcefc13c2022-10-26 15:47:24 +08001908 seg_flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
1909 error = wrapper_addPlaybackSegment(ctx, p_seg_info, p_pids, seg_flags);
wentao.maa210e5e2022-10-12 16:10:03 +08001910 if (error == DVR_FAILURE) {
1911 DVR_WRAPPER_WARN("adding playback segment fails");
hualing chenb9a02922021-12-14 11:29:47 +08001912 break;
wentao.maa210e5e2022-10-12 16:10:03 +08001913 }
hualing chenb9a02922021-12-14 11:29:47 +08001914
1915 /*copy the 1st segment*/
1916 if (got_1st_seg == 0) {
Wentao MA4d85ff32022-09-23 11:36:18 +08001917 seg_info_1st = *p_seg_info;
hualing chenb9a02922021-12-14 11:29:47 +08001918 got_1st_seg = 1;
1919 }
hualing chen92f3a142020-07-08 20:59:33 +08001920 }
hualing chenb9a02922021-12-14 11:29:47 +08001921 //free list
1922 DVR_RecordSegmentInfo_t *segment = NULL;
1923 DVR_RecordSegmentInfo_t *segment_tmp = NULL;
1924 list_for_each_entry_safe(segment, segment_tmp, &info_list, head)
1925 {
Wentao MAe2a2db92024-08-26 16:21:41 +08001926 list_del(&segment->head);
1927 free(segment);
hualing chenb9a02922021-12-14 11:29:47 +08001928 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001929 }
hualing chenb9a02922021-12-14 11:29:47 +08001930
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001931 free(p_segment_ids);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001932
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001933 /* return if no segment or fail to add */
1934 if (!error && got_1st_seg) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001935
Wentao MA270dc0f2022-08-23 13:17:26 +08001936 /*copy the obsolete information, must for timeshifting*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001937 if (ctx->playback.param_open.is_timeshift && ctx_record) {
1938 ctx->playback.obsolete = ctx_record->record.obsolete;
1939 }
1940
Wentao MA96f68962022-06-15 19:45:35 +08001941 DVR_WRAPPER_INFO("playback(sn:%ld) (%d) segments added\n", ctx->sn, i);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001942
1943 ctx->playback.reach_end = DVR_FALSE;
1944 if ((flags&DVR_PLAYBACK_STARTED_PAUSEDLIVE) == DVR_PLAYBACK_STARTED_PAUSEDLIVE)
1945 ctx->playback.speed = 0.0f;
1946 else
1947 ctx->playback.speed = 100.0f;
1948
1949 ctx->playback.pids_req = *p_pids;
Wentao MA270dc0f2022-08-23 13:17:26 +08001950 //calculate segment id and pos
hualing chen03fd4942021-07-15 15:56:41 +08001951 if (dvr_playback_check_limit(ctx->playback.player)) {
Gong Kefdb31922022-06-17 17:11:16 +08001952 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001953 dvr_wrapper_seek_playback(playback, 0);
Gong Kefdb31922022-06-17 17:11:16 +08001954 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001955 error = dvr_playback_start(ctx->playback.player, flags);
1956 } else {
wentao.maa210e5e2022-10-12 16:10:03 +08001957 dvr_playback_seek(ctx->playback.player, seg_info_1st.id, 0);
hualing chen03fd4942021-07-15 15:56:41 +08001958 error = dvr_playback_start(ctx->playback.player, flags);
Wentao MA96f68962022-06-15 19:45:35 +08001959 DVR_WRAPPER_INFO("playback(sn:%ld) seek(seg:%llu 0) for start (%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08001960 ctx->sn, seg_info_1st.id, error);
1961 }
Wentao MA96f68962022-06-15 19:45:35 +08001962 DVR_WRAPPER_INFO("playback(sn:%ld) started (%d)\n", ctx->sn, error);
hualing chen451c8f72022-03-09 13:05:52 +08001963 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001964 DVR_WRAPPER_INFO("playback(sn:%ld) started (%d)got_1st_seg:%d\n", ctx->sn, error, got_1st_seg);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001965 }
1966 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001967
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001968 if (ctx->playback.param_open.is_timeshift) {
1969 /*unlock the recorder locked above*/
1970 if (ctx_record && ctx_valid(ctx_record)) {
Gong Kefdb31922022-06-17 17:11:16 +08001971 wrapper_mutex_unlock(&ctx_record->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001972 DVR_WRAPPER_INFO("playback(sn:%ld), record(sn:%ld) unlocked ok due to timeshift\n",
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001973 ctx->sn, ctx_record->sn);
1974 }
1975 }
Gong Kefdb31922022-06-17 17:11:16 +08001976 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001977
1978 return error;
1979}
hualing chen002e5b92022-02-23 17:51:21 +08001980//stop record and playback
1981int dvr_wrapper_stop_timeshift (DVR_WrapperPlayback_t playback)
1982{
1983 DVR_WrapperCtx_t *ctx_record = NULL;/*for timeshift*/
1984 int error;
Wentao MA804bab12022-11-29 10:01:26 +08001985 DVR_WRAPPER_INFO("libdvr_api, stop_timeshift");
hualing chen002e5b92022-02-23 17:51:21 +08001986
1987 //stop timeshift record
1988 ctx_record = ctx_getRecord(sn_timeshift_record);
wentao.maa210e5e2022-10-12 16:10:03 +08001989 dvr_wrapper_stop_record((DVR_WrapperRecord_t)sn_timeshift_record);
hualing chen002e5b92022-02-23 17:51:21 +08001990
Wentao MA96f68962022-06-15 19:45:35 +08001991 DVR_WRAPPER_INFO("stop timeshift ...stop play\n");
hualing chen002e5b92022-02-23 17:51:21 +08001992 //stop play
1993 error = dvr_wrapper_stop_playback(playback);
1994 //del timeshift file
1995 if (ctx_record != NULL) {
Wentao MA96f68962022-06-15 19:45:35 +08001996 DVR_WRAPPER_INFO("del timeshift(sn:%ld) ...3\n", ctx_record->sn);
hualing chen002e5b92022-02-23 17:51:21 +08001997 error = dvr_segment_del_by_location(ctx_record->record.param_open.location);
1998 }
1999 return error;
2000}
2001//start record and start playback
2002int dvr_wrapper_restart_timeshift(DVR_WrapperPlayback_t playback, DVR_PlaybackFlag_t flags, DVR_PlaybackPids_t *p_pids)
2003{
2004 DVR_WrapperCtx_t *ctx;
2005 DVR_RecordStartParams_t *start_param;
2006 int error;
2007
2008 ctx = ctx_getRecord((unsigned long)sn_timeshift_record);
2009 DVR_RETURN_IF_FALSE(ctx);
2010
Gong Kefdb31922022-06-17 17:11:16 +08002011 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08002012 DVR_WRAPPER_INFO("libdvr_api, restart_timeshift (sn:%ld) location:%s",
2013 ctx->sn, ctx->record.param_open.location);
Gong Kefdb31922022-06-17 17:11:16 +08002014 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen002e5b92022-02-23 17:51:21 +08002015
hualing chen451c8f72022-03-09 13:05:52 +08002016 {
2017 //clear old record status
2018 // struct {
2019 // DVR_WrapperRecordOpenParams_t param_open;
2020 // DVR_RecordStartParams_t param_start;
2021 // DVR_RecordStartParams_t param_update;
2022 // DVR_RecordHandle_t recorder;
2023 // DVR_RecordEventFunction_t event_fn;
2024 // void *event_userdata;
2025
2026 // /*total status = seg_status + status + obsolete*/
2027 // DVR_RecordStatus_t seg_status; /**<status of current segment*/
2028 // DVR_WrapperRecordStatus_t status; /**<status of remaining segments*/
2029 // uint64_t next_segment_id;
2030
2031 // DVR_WrapperInfo_t obsolete; /**<data obsolete due to the max limit*/
2032 // } record;
2033 memset(&(ctx->record.seg_status), 0, sizeof(DVR_RecordStatus_t));
2034 memset(&(ctx->record.status), 0, sizeof(DVR_WrapperRecordStatus_t));
2035 memset(&(ctx->record.obsolete), 0, sizeof(DVR_WrapperInfo_t));
2036 }
2037
hualing chen002e5b92022-02-23 17:51:21 +08002038 start_param = &ctx->record.param_start;
2039
2040 error = dvr_record_start_segment(ctx->record.recorder, start_param);
2041 {
2042 DVR_RecordSegmentInfo_t new_seg_info =
2043 { .id = start_param->segment.segment_id, };
2044 wrapper_addRecordSegment(ctx, &new_seg_info);
Wentao MA96f68962022-06-15 19:45:35 +08002045 DVR_WRAPPER_INFO("re record(sn:%ld) started = (%d)start id[%lld]id+[%lld]update id[%lld]\n", ctx->sn, error, start_param->segment.segment_id, ctx->record.next_segment_id, ctx->record.param_update.segment.segment_id);
hualing chen451c8f72022-03-09 13:05:52 +08002046 ctx->record.next_segment_id = start_param->segment.segment_id + 1;
2047 DVR_RecordStartParams_t *update_param;
2048 update_param = &ctx->record.param_update;
2049 memcpy(update_param, start_param, sizeof(*update_param));
2050 int i = 0;
2051 for (i = 0; i < update_param->segment.nb_pids; i++)
2052 update_param->segment.pid_action[i] = DVR_RECORD_PID_KEEP;
hualing chen002e5b92022-02-23 17:51:21 +08002053 }
2054
Wentao MA96f68962022-06-15 19:45:35 +08002055 DVR_WRAPPER_INFO("re record(sn:%ld) started = (%d)\n", ctx->sn, error);
hualing chen002e5b92022-02-23 17:51:21 +08002056
Gong Kefdb31922022-06-17 17:11:16 +08002057 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen002e5b92022-02-23 17:51:21 +08002058
2059 //start play
Wentao MA96f68962022-06-15 19:45:35 +08002060 DVR_WRAPPER_INFO("re start play and clear old status\n");
hualing chen451c8f72022-03-09 13:05:52 +08002061 //clear play statue
2062 ctx = ctx_getPlayback((unsigned long)playback);
2063 if (ctx) {
Wentao MA4d85ff32022-09-23 11:36:18 +08002064 //reset old playback status
hualing chen451c8f72022-03-09 13:05:52 +08002065 // struct {
2066 // DVR_WrapperPlaybackOpenParams_t param_open;
2067 // DVR_PlaybackHandle_t player;
2068 // DVR_PlaybackEventFunction_t event_fn;
2069 // void *event_userdata;
2070
2071 // /*total status = seg_status + status*/
2072 // DVR_PlaybackStatus_t seg_status;
2073 // DVR_WrapperPlaybackStatus_t status;
2074 // DVR_PlaybackPids_t pids_req;
2075 // DVR_PlaybackEvent_t last_event;
2076 // float speed;
2077 // DVR_Bool_t reach_end;
2078
2079 // DVR_WrapperInfo_t obsolete;
2080 // DVR_Bool_t tf_full;
2081 // } playback;
Wentao MA4d85ff32022-09-23 11:36:18 +08002082 ctx->playback.tf_full = DVR_FALSE;
2083 ctx->playback.reach_end = DVR_FALSE;
hualing chen451c8f72022-03-09 13:05:52 +08002084 memset(&(ctx->playback.last_event), 0, sizeof(DVR_PlaybackEvent_t));
2085 memset(&(ctx->playback.seg_status), 0, sizeof(DVR_PlaybackStatus_t));
2086 memset(&(ctx->playback.status), 0, sizeof(DVR_WrapperPlaybackStatus_t));
2087 memset(&(ctx->playback.obsolete), 0, sizeof(DVR_WrapperInfo_t));
2088 }
hualing chen002e5b92022-02-23 17:51:21 +08002089 error = dvr_wrapper_start_playback(playback, flags, p_pids);
2090 return error;
2091}
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002092
2093int dvr_wrapper_stop_playback (DVR_WrapperPlayback_t playback)
2094{
2095 DVR_WrapperCtx_t *ctx;
2096 int error;
2097
2098 DVR_RETURN_IF_FALSE(playback);
2099
2100 ctx = ctx_getPlayback((unsigned long)playback);
2101 DVR_RETURN_IF_FALSE(ctx);
2102
Gong Kefdb31922022-06-17 17:11:16 +08002103 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08002104 DVR_WRAPPER_INFO("libdvr_api, stop_playback (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002105 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002106
2107 error = dvr_playback_stop(ctx->playback.player, DVR_TRUE);
2108
2109 {
2110 /*remove all segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002111 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002112
wentao.mafd5283f2022-10-14 09:51:13 +08002113 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08002114 // prefetch() here incurring self_assign is used to avoid some compiling
2115 // warnings.
2116 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002117 list_for_each_entry(p_seg, &ctx->segments, head) {
2118 error = dvr_playback_remove_segment(ctx->playback.player, p_seg->playback_info.segment_id);
Wentao MA96f68962022-06-15 19:45:35 +08002119 DVR_WRAPPER_INFO("playback(sn:%ld) remove seg(%lld) (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08002120 ctx->sn, p_seg->playback_info.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002121 }
2122 ctx_freeSegments(ctx);
2123 }
2124
Wentao MA96f68962022-06-15 19:45:35 +08002125 DVR_WRAPPER_INFO("playback(sn:%ld) stopped (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002126 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002127
2128 return error;
2129}
2130
2131int dvr_wrapper_pause_playback (DVR_WrapperPlayback_t playback)
2132{
2133 DVR_WrapperCtx_t *ctx;
2134 int error;
2135
2136 DVR_RETURN_IF_FALSE(playback);
2137
2138 ctx = ctx_getPlayback((unsigned long)playback);
2139 DVR_RETURN_IF_FALSE(ctx);
2140
Gong Kefdb31922022-06-17 17:11:16 +08002141 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08002142 DVR_WRAPPER_INFO("libdvr_api, pause_playback (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002143 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen36e0dfd2020-05-02 16:33:06 +08002144 //clear end event
Zhiqiang Hanb723cdb2020-05-09 11:10:29 +08002145 if (ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_END)
hualing chen36e0dfd2020-05-02 16:33:06 +08002146 ctx->playback.last_event = DVR_PLAYBACK_EVENT_TRANSITION_OK;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002147
2148 error = dvr_playback_pause(ctx->playback.player, DVR_FALSE);
2149
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002150 ctx->playback.speed = 0.0f;
2151
Wentao MA96f68962022-06-15 19:45:35 +08002152 DVR_WRAPPER_INFO("playback(sn:%ld) paused (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002153 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002154
2155 return error;
2156}
2157
2158int dvr_wrapper_resume_playback (DVR_WrapperPlayback_t playback)
2159{
2160 DVR_WrapperCtx_t *ctx;
2161 int error;
2162
2163 DVR_RETURN_IF_FALSE(playback);
2164
2165 ctx = ctx_getPlayback((unsigned long)playback);
2166 DVR_RETURN_IF_FALSE(ctx);
hualing chen03fd4942021-07-15 15:56:41 +08002167 //if set limit.we need check if seek to valid data when resume
2168 uint32_t time_offset = ctx->playback.status.info_cur.time + ctx->playback.status.info_obsolete.time;
2169 if (dvr_playback_check_limit(ctx->playback.player)) {
2170 int expired = dvr_playback_calculate_expiredlen(ctx->playback.player);
2171 if (expired > time_offset) {
Wentao MA96f68962022-06-15 19:45:35 +08002172 DVR_WRAPPER_INFO("seek before resume reset offset playback(sn:%ld) (off:%d expired:%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08002173 ctx->sn, time_offset, expired);
2174 time_offset = expired;
2175 dvr_wrapper_seek_playback(playback, time_offset);
2176 }
2177 }
Gong Kefdb31922022-06-17 17:11:16 +08002178 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08002179 DVR_WRAPPER_INFO("libdvr_api, resume_playback (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002180 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002181
2182 error = dvr_playback_resume(ctx->playback.player);
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002183 ctx->playback.speed = 100.0f;
2184
Wentao MA96f68962022-06-15 19:45:35 +08002185 DVR_WRAPPER_INFO("playback(sn:%ld) resumed (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002186 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002187
2188 return error;
2189}
2190
2191int dvr_wrapper_set_playback_speed (DVR_WrapperPlayback_t playback, float speed)
2192{
2193 DVR_WrapperCtx_t *ctx;
2194 int error;
2195 DVR_PlaybackSpeed_t dvr_speed = {
2196 .speed = { speed },
2197 .mode = (speed > 0) ? DVR_PLAYBACK_FAST_FORWARD : DVR_PLAYBACK_FAST_BACKWARD
2198 };
2199
2200 DVR_RETURN_IF_FALSE(playback);
2201
2202 ctx = ctx_getPlayback((unsigned long)playback);
2203 DVR_RETURN_IF_FALSE(ctx);
2204
Gong Kefdb31922022-06-17 17:11:16 +08002205 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08002206 DVR_WRAPPER_INFO("libdvr_api, set_playback_speed (sn:%ld) speed:%d", ctx->sn, (int)speed);
Gong Kefdb31922022-06-17 17:11:16 +08002207 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002208
2209 error = dvr_playback_set_speed(ctx->playback.player, dvr_speed);
2210
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002211 ctx->playback.speed = speed;
2212
Wentao MA96f68962022-06-15 19:45:35 +08002213 DVR_WRAPPER_INFO("playback(sn:%ld) speeded(x%f) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002214 ctx->sn, speed, error);
Gong Kefdb31922022-06-17 17:11:16 +08002215 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002216
2217 return error;
2218}
2219
hualing chen03fd4942021-07-15 15:56:41 +08002220int dvr_wrapper_setlimit_playback (DVR_WrapperPlayback_t playback, uint64_t time, int32_t limit)
2221{
2222 DVR_WrapperCtx_t *ctx;
2223 int error;
2224
2225 DVR_RETURN_IF_FALSE(playback);
2226
2227 ctx = ctx_getPlayback((unsigned long)playback);
2228 DVR_RETURN_IF_FALSE(ctx);
2229
Gong Kefdb31922022-06-17 17:11:16 +08002230 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002231
Wentao MA804bab12022-11-29 10:01:26 +08002232 DVR_WRAPPER_INFO("libdvr_api, setlimit_playback (sn:%ld) time:%lld, limit:%d",
2233 ctx->sn, time, limit);
Gong Kefdb31922022-06-17 17:11:16 +08002234 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002235
2236 error = dvr_playback_setlimit(ctx->playback.player, time, limit);
Wentao MAe8ba5172022-08-09 11:18:17 +08002237 DVR_WRAPPER_INFO("playback(sn:%ld) set_limit(time:%lld limit:%d) ...\n", ctx->sn, time, limit);
hualing chen03fd4942021-07-15 15:56:41 +08002238
Gong Kefdb31922022-06-17 17:11:16 +08002239 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002240
2241 return error;
2242}
2243
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002244int dvr_wrapper_seek_playback (DVR_WrapperPlayback_t playback, uint32_t time_offset)
2245{
2246 DVR_WrapperCtx_t *ctx;
2247 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08002248 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Wentao MA804bab12022-11-29 10:01:26 +08002249 uint64_t segment_id = ULLONG_MAX;
2250 uint32_t segment_offset = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002251
2252 DVR_RETURN_IF_FALSE(playback);
2253
2254 ctx = ctx_getPlayback((unsigned long)playback);
2255 DVR_RETURN_IF_FALSE(ctx);
2256
Gong Kefdb31922022-06-17 17:11:16 +08002257 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002258
Wentao MA804bab12022-11-29 10:01:26 +08002259 DVR_WRAPPER_INFO("libdvr_api, seek_playback (sn:%ld) offset:%dms", ctx->sn, time_offset);
Gong Kefdb31922022-06-17 17:11:16 +08002260 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002261
hualing chen03fd4942021-07-15 15:56:41 +08002262 //if set limit info we need check ts data is
2263 //expired when seek
2264 if (dvr_playback_check_limit(ctx->playback.player)) {
2265 int expired = dvr_playback_calculate_expiredlen(ctx->playback.player);
2266 if (expired > time_offset) {
Wentao MA96f68962022-06-15 19:45:35 +08002267 DVR_WRAPPER_INFO("seek reset offset playback(sn:%ld) (off:%d expired:%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08002268 ctx->sn, time_offset, expired);
2269 time_offset = expired;
2270 }
2271 }
Wentao MAf51f0142023-09-27 13:59:48 +08002272 ctx->playback.reach_end = DVR_FALSE;
hualing chen03fd4942021-07-15 15:56:41 +08002273
Wentao MA804bab12022-11-29 10:01:26 +08002274 const uint32_t obsolete_time = (uint32_t)ctx->playback.obsolete.time;
2275 DVR_WrapperPlaybackSegmentInfo_t *p_seg_first = ctx->segments.c_prev;
2276 DVR_WrapperPlaybackSegmentInfo_t *p_seg_last = ctx->segments.c_next;
2277 const uint64_t first_id = p_seg_first->seg_info.id;
2278 const uint64_t last_id = p_seg_last->seg_info.id;
2279 const uint32_t last_duration = p_seg_last->seg_info.duration;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002280
Wentao MA804bab12022-11-29 10:01:26 +08002281 if (time_offset <= obsolete_time) {
2282 segment_id = first_id;
2283 segment_offset = 0;
2284 DVR_WRAPPER_WARN("time_offset %u isn't greater than obsolete time %u, "
2285 "so seek to beginning position of segment %llu",
2286 time_offset,obsolete_time,segment_id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002287 } else {
Wentao MA804bab12022-11-29 10:01:26 +08002288 uint32_t total_duration = 0;
2289 // This error is suppressed as the macro code is picked from kernel.
2290 // prefetch() here incurring self_assign is used to avoid some compiling
2291 // warnings.
2292 // coverity[self_assign]
2293 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
2294 const uint32_t segment_begin = obsolete_time + total_duration;
2295 const uint32_t segment_end = segment_begin + p_seg->seg_info.duration;
2296 if (time_offset >= segment_begin && time_offset <= segment_end) {
2297 segment_id = p_seg->seg_info.id;
2298 segment_offset = time_offset - segment_begin;
2299 break;
2300 }
2301 total_duration += p_seg->seg_info.duration;
2302 }
2303 if (segment_id == ULLONG_MAX) {
2304 segment_id = last_id;
2305 segment_offset = last_duration;
2306 DVR_WRAPPER_WARN("time_offset %u is out of range, so seek to"
2307 " the end position of segment %llu",time_offset,segment_id);
2308 }
Zhiqiang Hane1dd4192024-06-17 11:29:20 +08002309
2310 /*
2311 1. timeshift or playback of a running recording
2312 2. live_gap set
2313 3. keep a gap to the live, to avoid underflow of player's cache
2314 */
2315 int live_gap = dvr_prop_read_int("vendor.tv.libdvr.live_gap", 0);
2316
2317 if (live_gap) {
2318
2319 if (ctx->playback.param_open.is_timeshift
2320 || ctx_isPlay_recording(ctx->playback.param_open.location)) {
2321
2322 if (segment_id == last_id && segment_offset == last_duration) {
2323 DVR_WRAPPER_INFO("seek to the end, round back %dms to make play smoothly, %u-%d",
2324 live_gap, segment_offset, live_gap);
2325
2326 segment_offset -= live_gap;
2327 }
2328 }
2329 }
2330
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002331 }
2332
Wentao MA804bab12022-11-29 10:01:26 +08002333 DVR_WRAPPER_INFO("seek playback(sn:%ld) (segment_id:%llu, segment_offset:%u)\n",
2334 ctx->sn, segment_id, segment_offset);
2335 error = dvr_playback_seek(ctx->playback.player, segment_id, segment_offset);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002336
Gong Kefdb31922022-06-17 17:11:16 +08002337 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002338
2339 return error;
2340}
2341
2342int dvr_wrapper_update_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackPids_t *p_pids)
2343{
2344 DVR_WrapperCtx_t *ctx;
2345 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08002346 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002347
2348 DVR_RETURN_IF_FALSE(playback);
2349 DVR_RETURN_IF_FALSE(p_pids);
2350
2351 ctx = ctx_getPlayback((unsigned long)playback);
2352 DVR_RETURN_IF_FALSE(ctx);
2353
Gong Kefdb31922022-06-17 17:11:16 +08002354 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002355
Wentao MA804bab12022-11-29 10:01:26 +08002356 DVR_WRAPPER_INFO("libdvr_api, update_playback (sn:%ld) v/a(%d:%d/%d:%d)",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002357 ctx->sn,
2358 p_pids->video.pid, p_pids->video.format,
2359 p_pids->audio.pid, p_pids->audio.format);
Gong Kefdb31922022-06-17 17:11:16 +08002360 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002361
2362 ctx->playback.pids_req = *p_pids;
2363
2364 error = 0;
wentao.mafd5283f2022-10-14 09:51:13 +08002365 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08002366 // prefetch() here incurring self_assign is used to avoid some compiling
2367 // warnings.
2368 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002369 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002370 /*should update the whole list of segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002371 /*if (p_seg->seg_info.id == ctx->current_segment_id)*/ {
2372 /*list_for_each_entry_from(p_seg, &ctx->segments, head)*/ {
2373 /*check update for pids*/
2374 if (memcmp(&p_seg->playback_info.pids, p_pids, sizeof(*p_pids)) != 0) {
2375 p_seg->playback_info.pids = *p_pids;
2376 error = dvr_playback_update_segment_pids(ctx->playback.player, p_seg->seg_info.id, p_pids);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002377 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08002378 DVR_WRAPPER_INFO("failed to playback(sn:%ld) update segment(id:%lld) pids (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08002379 ctx->sn, p_seg->seg_info.id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002380 /*do not break, let list updated*/
2381 }
2382 }
2383 }
2384 /*break;*/
2385 }
2386 }
2387
Wentao MA96f68962022-06-15 19:45:35 +08002388 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002389 ctx->sn,
2390 p_pids->video.pid, p_pids->video.format,
2391 p_pids->audio.pid, p_pids->audio.format,
2392 error);
2393
Gong Kefdb31922022-06-17 17:11:16 +08002394 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002395
2396 return error;
2397}
2398
hualing chena5f03222021-12-02 11:22:35 +08002399int dvr_wrapper_only_update_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackPids_t *p_pids)
2400{
2401 DVR_WrapperCtx_t *ctx;
2402 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08002403 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
hualing chena5f03222021-12-02 11:22:35 +08002404
2405 DVR_RETURN_IF_FALSE(playback);
2406 DVR_RETURN_IF_FALSE(p_pids);
2407
2408 ctx = ctx_getPlayback((unsigned long)playback);
2409 DVR_RETURN_IF_FALSE(ctx);
2410
Gong Kefdb31922022-06-17 17:11:16 +08002411 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002412
Wentao MA804bab12022-11-29 10:01:26 +08002413 DVR_WRAPPER_INFO("libdvr_api, only_update_playback (sn:%ld) v/a(%d:%d/%d:%d)",
hualing chena5f03222021-12-02 11:22:35 +08002414 ctx->sn,
2415 p_pids->video.pid, p_pids->video.format,
2416 p_pids->audio.pid, p_pids->audio.format);
Gong Kefdb31922022-06-17 17:11:16 +08002417 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002418
2419 ctx->playback.pids_req = *p_pids;
2420
2421 error = 0;
wentao.mafd5283f2022-10-14 09:51:13 +08002422 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08002423 // prefetch() here incurring self_assign is used to avoid some compiling
2424 // warnings.
2425 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002426 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
hualing chena5f03222021-12-02 11:22:35 +08002427 /*should update the whole list of segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002428 /*if (p_seg->seg_info.id == ctx->current_segment_id)*/ {
2429 /*list_for_each_entry_from(p_seg, &ctx->segments, head)*/ {
2430 /*check update for pids*/
2431 if (memcmp(&p_seg->playback_info.pids, p_pids, sizeof(*p_pids)) != 0) {
2432 p_seg->playback_info.pids = *p_pids;
2433 error = dvr_playback_only_update_segment_pids(ctx->playback.player, p_seg->seg_info.id, p_pids);
hualing chena5f03222021-12-02 11:22:35 +08002434 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08002435 DVR_WRAPPER_INFO("failed to playback(sn:%ld) update segment(id:%lld) pids (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08002436 ctx->sn, p_seg->seg_info.id, error);
hualing chena5f03222021-12-02 11:22:35 +08002437 /*do not break, let list updated*/
2438 }
2439 }
2440 }
2441 /*break;*/
2442 }
2443 }
2444
Wentao MA96f68962022-06-15 19:45:35 +08002445 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) (%d)\n",
hualing chena5f03222021-12-02 11:22:35 +08002446 ctx->sn,
2447 p_pids->video.pid, p_pids->video.format,
2448 p_pids->audio.pid, p_pids->audio.format,
2449 error);
2450
Gong Kefdb31922022-06-17 17:11:16 +08002451 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002452
2453 return error;
2454}
2455
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002456int dvr_wrapper_get_playback_status(DVR_WrapperPlayback_t playback, DVR_WrapperPlaybackStatus_t *status)
2457{
2458 DVR_WrapperCtx_t *ctx;
2459 DVR_WrapperPlaybackStatus_t s;
2460 DVR_PlaybackStatus_t play_status;
2461 int error;
2462
2463 DVR_RETURN_IF_FALSE(playback);
2464 DVR_RETURN_IF_FALSE(status);
2465
2466 ctx = ctx_getPlayback((unsigned long)playback);
2467 DVR_RETURN_IF_FALSE(ctx);
2468
Gong Kefdb31922022-06-17 17:11:16 +08002469 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002470
Gong Kefdb31922022-06-17 17:11:16 +08002471 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002472
Wentao MAe2a2db92024-08-26 16:21:41 +08002473 memset((void*)&play_status,0,sizeof(DVR_PlaybackStatus_t));
Wentao MA804bab12022-11-29 10:01:26 +08002474 dvr_playback_get_status(ctx->playback.player, &play_status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002475
2476 ctx->playback.seg_status = play_status;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002477 error = process_generatePlaybackStatus(ctx, &s);
2478
hualing chenb5cd42e2020-04-15 17:03:34 +08002479 if (ctx->playback.reach_end == DVR_TRUE && ctx->playback.param_open.is_timeshift == DVR_FALSE) {
2480 //reach end need set full time to cur.so app can exist playback.
Wentao MA96f68962022-06-15 19:45:35 +08002481 DVR_WRAPPER_INFO("set cur time to full time, reach end occur");
hualing chenb5cd42e2020-04-15 17:03:34 +08002482 s.info_cur.time = s.info_full.time;
2483 }
Wentao MA804bab12022-11-29 10:01:26 +08002484 DVR_WRAPPER_INFO("get_playback_status (sn:%ld) state/cur/full/obsolete(%d/%ld/%ld/%ld)",
2485 ctx->sn, s.state, s.info_cur.time, s.info_full.time, s.info_obsolete.time);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002486
2487 *status = s;
2488
Gong Kefdb31922022-06-17 17:11:16 +08002489 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002490
2491 return error;
2492}
2493
hualing chen266b9502020-04-04 17:39:39 +08002494int dvr_wrapper_set_playback_secure_buffer (DVR_WrapperPlayback_t playback, uint8_t *p_secure_buf, uint32_t len)
2495{
2496 DVR_WrapperCtx_t *ctx;
2497 int error;
2498
2499 DVR_RETURN_IF_FALSE(playback);
2500 DVR_RETURN_IF_FALSE(p_secure_buf);
2501
2502 ctx = ctx_getPlayback((unsigned long)playback);
2503 DVR_RETURN_IF_FALSE(ctx);
2504
Gong Kefdb31922022-06-17 17:11:16 +08002505 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002506 error = dvr_playback_set_secure_buffer(ctx->playback.player, p_secure_buf, len);
Gong Kefdb31922022-06-17 17:11:16 +08002507 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002508 return error;
2509}
2510
2511int dvr_wrapper_set_playback_decrypt_callback (DVR_WrapperPlayback_t playback, DVR_CryptoFunction_t func, void *userdata)
2512{
2513 DVR_WrapperCtx_t *ctx;
2514 int error;
2515
2516 DVR_RETURN_IF_FALSE(playback);
2517 DVR_RETURN_IF_FALSE(func);
2518
2519 ctx = ctx_getPlayback((unsigned long)playback);
2520 DVR_RETURN_IF_FALSE(ctx);
2521
Gong Kefdb31922022-06-17 17:11:16 +08002522 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002523 error = dvr_playback_set_decrypt_callback(ctx->playback.player, func, userdata);
Gong Kefdb31922022-06-17 17:11:16 +08002524 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002525 return error;
2526}
2527
Zhiqiang Han620b9252021-11-09 14:23:20 +08002528int dvr_wrapper_segment_del_by_location (const char *location)
2529{
2530 char fpath[DVR_MAX_LOCATION_SIZE];
2531
2532 DVR_RETURN_IF_FALSE(location);
2533
2534 /*del the stats file*/
Wentao MAe2a2db92024-08-26 16:21:41 +08002535 snprintf(fpath, DVR_MAX_LOCATION_SIZE-6, "%s.stats", location);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002536 unlink(fpath);
2537
2538 return dvr_segment_del_by_location(location);
2539}
2540
2541int dvr_wrapper_segment_get_info_by_location (const char *location, DVR_WrapperInfo_t *p_info)
2542{
2543 FILE *fp;
2544 char fpath[DVR_MAX_LOCATION_SIZE];
2545
2546 DVR_RETURN_IF_FALSE(location);
2547 DVR_RETURN_IF_FALSE(p_info);
2548
2549 if (p_info)
2550 memset(p_info, 0, sizeof(p_info[0]));
2551
2552 memset(fpath, 0, sizeof(fpath));
Wentao MAe2a2db92024-08-26 16:21:41 +08002553 snprintf(fpath, DVR_MAX_LOCATION_SIZE-6, "%s.stats", location);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002554
2555 /*stats file exists*/
2556 if ((fp = fopen(fpath, "r"))) {
2557 char buf[256];
2558
2559 if (fgets(buf, sizeof(buf), fp) != NULL
2560 && (sscanf(buf, ":%llu:%lu:%u",
2561 &p_info->size,
2562 &p_info->time,
2563 &p_info->pkts) == 3)) {
2564 fclose(fp);
Wentao MA96f68962022-06-15 19:45:35 +08002565 DVR_WRAPPER_INFO("rec(%s) t/s/p:(%lu/%llu/%u)\n", location, p_info->time, p_info->size, p_info->pkts);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002566 return DVR_SUCCESS;
2567 }
Zhiqiang Hanb9785922021-11-26 18:47:39 +08002568 fclose(fp);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002569 }
2570
2571 /*fallback, slow on mass files*/
Wentao MA96f68962022-06-15 19:45:35 +08002572 DVR_WRAPPER_INFO("rec '%s.stats' invalid.\n", location);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002573
2574 int error;
2575 uint32_t n_ids;
2576 uint64_t *p_ids;
Zhiqiang Han620b9252021-11-09 14:23:20 +08002577
hualing chen8aed9582021-12-24 17:59:56 +08002578 error = dvr_segment_get_list(location, &n_ids, &p_ids);
hualing chenb9a02922021-12-14 11:29:47 +08002579
Zhiqiang Han620b9252021-11-09 14:23:20 +08002580 if (!error) {
2581 int i;
hualing chenb9a02922021-12-14 11:29:47 +08002582 struct list_head info_list; /**< segment list head*/
2583 INIT_LIST_HEAD(&info_list);
2584
2585 //we need free info list buf when we used end.
hualing chen8aed9582021-12-24 17:59:56 +08002586 error = dvr_segment_get_allInfo(location, &info_list);
2587 if (error == DVR_FAILURE) {
wentao.maa210e5e2022-10-12 16:10:03 +08002588 DVR_RecordSegmentInfo_t info = { .id = 0, .nb_pids = 0,
2589 .pids = {0}, .duration = 0, .size = 0, .nb_packets = 0 };
hualing chenb9a02922021-12-14 11:29:47 +08002590
2591 memset(&info, 0, sizeof(info));
2592 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08002593 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chen8aed9582021-12-24 17:59:56 +08002594 location, 0, error);
hualing chenb9a02922021-12-14 11:29:47 +08002595
wentao.maf57dd232022-10-08 16:07:29 +08002596 // Tainted data issue originating from fgets seem false positive, so we
2597 // just suppress it here.
2598 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08002599 for (i = 0; i < n_ids; i++) {
hualing chen8aed9582021-12-24 17:59:56 +08002600 error = dvr_segment_get_info(location, p_ids[i], &info);
hualing chenb9a02922021-12-14 11:29:47 +08002601 if (!error) {
2602 p_info->size += info.size;
2603 p_info->time += info.duration;
2604 p_info->pkts += info.nb_packets;
2605 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002606 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chenb9a02922021-12-14 11:29:47 +08002607 break;
2608 }
2609 }
2610 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002611 DVR_WRAPPER_INFO("get list segment_nb::%d",n_ids);
wentao.maf57dd232022-10-08 16:07:29 +08002612 // Tainted data issue originating from fgets seem false positive, so we
2613 // just suppress it here.
2614 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08002615 for (i = 0; i < n_ids; i++) {
2616
2617 DVR_RecordSegmentInfo_t *seg_info;
2618 DVR_PlaybackSegmentFlag_t flags;
2619 int found = 0;
wentao.mafd5283f2022-10-14 09:51:13 +08002620 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08002621 // prefetch() here incurring self_assign is used to avoid some compiling
2622 // warnings.
2623 // coverity[self_assign]
hualing chenb9a02922021-12-14 11:29:47 +08002624 list_for_each_entry(seg_info, &info_list, head)
2625 {
hualing chen8aed9582021-12-24 17:59:56 +08002626 if (seg_info->id == p_ids[i]) {
hualing chenb9a02922021-12-14 11:29:47 +08002627 found = 1;
2628 break;
2629 }
2630 }
2631 if (!found) {
Wentao MA96f68962022-06-15 19:45:35 +08002632 DVR_WRAPPER_INFO("get segment info::%d [%d]n_ids[%d]error", i, p_ids[i], n_ids);
hualing chen8aed9582021-12-24 17:59:56 +08002633 if (p_ids[i] == n_ids - 1) {
wentao.maa210e5e2022-10-12 16:10:03 +08002634 DVR_RecordSegmentInfo_t info = { .id = 0, .nb_pids = 0,
2635 .pids = {0}, .duration = 0, .size = 0, .nb_packets = 0 };
Wentao MA96f68962022-06-15 19:45:35 +08002636 DVR_WRAPPER_INFO("get last segment info::%d [%d]n_ids[%d] from subfile", i, p_ids[i], n_ids);
hualing chen8aed9582021-12-24 17:59:56 +08002637 error = dvr_segment_get_info(location, p_ids[i], &info);
2638 if (!error) {
2639 p_info->size += info.size;
2640 p_info->time += info.duration;
2641 p_info->pkts += info.nb_packets;
2642 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002643 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chen8aed9582021-12-24 17:59:56 +08002644 break;
2645 }
2646 }
hualing chenb9a02922021-12-14 11:29:47 +08002647 continue;
2648 }
2649
2650 if (!error) {
2651 p_info->size += seg_info->size;
2652 p_info->time += seg_info->duration;
2653 p_info->pkts += seg_info->nb_packets;
2654 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002655 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chenb9a02922021-12-14 11:29:47 +08002656 break;
2657 }
2658 }
2659 //free list
2660 DVR_RecordSegmentInfo_t *segment = NULL;
2661 DVR_RecordSegmentInfo_t *segment_tmp = NULL;
2662 list_for_each_entry_safe(segment, segment_tmp, &info_list, head)
2663 {
Wentao MAe2a2db92024-08-26 16:21:41 +08002664 list_del(&segment->head);
2665 free(segment);
hualing chenb9a02922021-12-14 11:29:47 +08002666 }
2667 }
2668 free(p_ids);
Zhiqiang Hanb9785922021-11-26 18:47:39 +08002669 } else {
2670 n_ids = 0;
Zhiqiang Han620b9252021-11-09 14:23:20 +08002671 }
Wentao MA96f68962022-06-15 19:45:35 +08002672 DVR_WRAPPER_INFO("rec(%s)... t/s/p:(%lu/%llu/%u) segs(%u) error(%d)\n", location, p_info->time, p_info->size, p_info->pkts, n_ids, error);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002673
2674 return (error)? DVR_FAILURE : DVR_SUCCESS;
2675}
2676
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002677static DVR_Result_t wrapper_record_event_handler(DVR_RecordEvent_t event, void *params, void *userdata)
2678{
wentao.maa210e5e2022-10-12 16:10:03 +08002679 DVR_WrapperEventCtx_t evt = {
2680 .sn = (unsigned long)userdata,
2681 .type = W_REC,
2682 .record.event = event,
2683 .record.status = *(DVR_RecordStatus_t *)params
2684 };
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002685
2686 DVR_RETURN_IF_FALSE(userdata);
2687
Wentao MA804bab12022-11-29 10:01:26 +08002688 DVR_WRAPPER_DEBUG("record event 0x%x (sn:%ld)", evt.record.event, evt.sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002689 return ctx_addRecordEvent(&evt);
2690}
2691
2692static DVR_Result_t wrapper_playback_event_handler(DVR_PlaybackEvent_t event, void *params, void *userdata)
2693{
wentao.maa210e5e2022-10-12 16:10:03 +08002694 DVR_WrapperEventCtx_t evt = {
2695 .sn = (unsigned long)userdata,
2696 .type = W_PLAYBACK,
2697 .playback.event = event,
2698 .playback.status = *(DVR_Play_Notify_t *)params
2699 };
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002700
2701 DVR_RETURN_IF_FALSE(userdata);
2702
2703 evt.sn = (unsigned long)userdata;
2704 evt.type = W_PLAYBACK;
2705 evt.playback.event = event;
2706 evt.playback.status = *(DVR_Play_Notify_t *)params;
Wentao MA804bab12022-11-29 10:01:26 +08002707 DVR_WRAPPER_DEBUG("playback event 0x%x (sn:%ld)", evt.playback.event, evt.sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002708 return ctx_addPlaybackEvent(&evt);
2709}
2710
2711static inline int process_notifyRecord(DVR_WrapperCtx_t *ctx, DVR_RecordEvent_t evt, DVR_WrapperRecordStatus_t *status)
2712{
Wentao MA270dc0f2022-08-23 13:17:26 +08002713 DVR_WRAPPER_INFO("notify(sn:%ld) evt(0x%x) statistic:time/size/pkts(%ld/%lld/%u) obsolete:(%ld/%llu/%u)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002714 ctx->sn,
2715 evt,
2716 status->info.time,
2717 status->info.size,
2718 status->info.pkts,
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002719 status->info_obsolete.time,
2720 status->info_obsolete.size,
2721 status->info_obsolete.pkts);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002722
2723 if (ctx->record.event_fn)
2724 return ctx->record.event_fn(evt, status, ctx->record.event_userdata);
2725 return 0;
2726}
2727
Zhiqiang Han620b9252021-11-09 14:23:20 +08002728static int wrapper_saveRecordStatistics(const char *location, DVR_WrapperRecordStatus_t *p_status)
2729{
2730 FILE *fp;
2731 char fpath[DVR_MAX_LOCATION_SIZE];
2732
2733 DVR_RETURN_IF_FALSE(location);
2734 DVR_RETURN_IF_FALSE(p_status);
2735
Wentao MAe2a2db92024-08-26 16:21:41 +08002736 snprintf(fpath, DVR_MAX_LOCATION_SIZE-6, "%s.stats", location);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002737
2738 /*stats file*/
2739 if ((fp = fopen(fpath, "w"))) {
2740 char buf[256];
2741 snprintf(buf, sizeof(buf), ":%llu:%lu:%u\n",
2742 p_status->info.size - p_status->info_obsolete.size,
2743 p_status->info.time - p_status->info_obsolete.time,
2744 p_status->info.pkts - p_status->info_obsolete.pkts);
2745 fputs(buf, fp);
Zhiqiang Handc3bfe52022-07-07 10:48:39 +08002746 fflush(fp);
Zhiqiang Hanc43a4d22023-10-25 15:24:19 +08002747 //fsync(fileno(fp));
Zhiqiang Han620b9252021-11-09 14:23:20 +08002748 fclose(fp);
2749 return DVR_SUCCESS;
2750 }
2751
2752 return DVR_FAILURE;
2753}
2754
2755
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002756static inline int record_startNextSegment(DVR_WrapperCtx_t *ctx)
2757{
2758 DVR_RecordStartParams_t param;
2759 DVR_RecordSegmentInfo_t seg_info;
2760 int i;
2761 int error;
2762
2763 memcpy(&param, &ctx->record.param_update, sizeof(param));
2764 memset(&ctx->record.param_update.segment, 0, sizeof(ctx->record.param_update.segment));
2765 ctx->record.param_update.segment.segment_id = ctx->record.next_segment_id++;
2766 for (i = 0; i < param.segment.nb_pids; i++) {
2767 if (param.segment.pid_action[i] != DVR_RECORD_PID_CLOSE) {
2768 ctx->record.param_update.segment.pids[ctx->record.param_update.segment.nb_pids] = param.segment.pids[i];
2769 ctx->record.param_update.segment.pid_action[ctx->record.param_update.segment.nb_pids] = DVR_RECORD_PID_KEEP;
2770 ctx->record.param_update.segment.nb_pids++;
2771 }
2772 }
Wentao MAe2a2db92024-08-26 16:21:41 +08002773 memset((void*)&seg_info,0,sizeof(DVR_RecordSegmentInfo_t));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002774 error = dvr_record_next_segment(ctx->record.recorder, &ctx->record.param_update, &seg_info);
2775 {
2776 DVR_RecordSegmentInfo_t new_seg_info =
2777 { .id = ctx->record.param_update.segment.segment_id, };
2778 wrapper_updateRecordSegment(ctx, &seg_info, U_ALL);
2779 wrapper_addRecordSegment(ctx, &new_seg_info);
2780 }
2781
Wentao MA96f68962022-06-15 19:45:35 +08002782 DVR_WRAPPER_INFO("record next segment(%llu)=(%d)\n", ctx->record.param_update.segment.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002783 return error;
2784}
2785
Wentao MA270dc0f2022-08-23 13:17:26 +08002786static inline int record_removeSegment(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordSegmentInfo_t *p_seg)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002787{
Wentao MA270dc0f2022-08-23 13:17:26 +08002788 return wrapper_removeRecordSegment(ctx, p_seg);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002789}
2790
2791/*should run periodically to update the current status*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002792static int process_generateRecordStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordStatus_t *status)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002793{
2794 /*the current seg is not covered in the statistics*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002795 DVR_WrapperRecordSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002796
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002797 /*re-calculate the all segments*/
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002798 memset(&ctx->record.status, 0, sizeof(ctx->record.status));
2799
2800 ctx->record.status.state = ctx->record.seg_status.state;
2801 ctx->record.status.pids.nb_pids = ctx->record.seg_status.info.nb_pids;
2802 memcpy(ctx->record.status.pids.pids,
2803 ctx->record.seg_status.info.pids,
2804 sizeof(ctx->record.status.pids.pids));
2805 ctx->current_segment_id = ctx->record.seg_status.info.id;
2806
wentao.mafd5283f2022-10-14 09:51:13 +08002807 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08002808 // prefetch() here incurring self_assign is used to avoid some compiling
2809 // warnings.
2810 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002811 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
2812 if (p_seg->info.id != ctx->record.seg_status.info.id) {
2813 ctx->record.status.info.time += p_seg->info.duration;
2814 ctx->record.status.info.size += p_seg->info.size;
2815 ctx->record.status.info.pkts += p_seg->info.nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002816 }
2817 }
2818
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002819 ctx->record.status.info_obsolete = ctx->record.obsolete;
2820
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002821 wrapper_updateRecordSegment(ctx, &ctx->record.seg_status.info, U_ALL);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002822
2823 if (status) {
2824 *status = ctx->record.status;
2825 status->info.time += ctx->record.seg_status.info.duration;
2826 status->info.size += ctx->record.seg_status.info.size;
2827 status->info.pkts += ctx->record.seg_status.info.nb_packets;
2828 }
2829
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002830 return DVR_SUCCESS;
2831}
2832
2833
2834static int process_handleRecordEvent(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
2835{
2836 DVR_WrapperRecordStatus_t status;
2837
2838 memset(&status, 0, sizeof(status));
2839
Wentao MA804bab12022-11-29 10:01:26 +08002840 DVR_WRAPPER_DEBUG("evt (sn:%ld) 0x%x (state:%d)\n",
2841 evt->sn, evt->record.event, evt->record.status.state);
hualing chend3b55ab2021-05-06 09:56:27 +08002842 if (ctx->record.param_update.segment.segment_id != evt->record.status.info.id) {
Wentao MA96f68962022-06-15 19:45:35 +08002843 DVR_WRAPPER_INFO("evt (sn:%ld) cur id:0x%x (event id:%d)\n",
Gong Ke2a0ebbe2021-05-25 15:22:50 +08002844 evt->sn, (int)ctx->record.param_update.segment.segment_id, (int)evt->record.status.info.id);
hualing chend3b55ab2021-05-06 09:56:27 +08002845 return 0;
2846 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002847 switch (evt->record.event)
2848 {
2849 case DVR_RECORD_EVENT_STATUS:
2850 {
2851 switch (evt->record.status.state)
2852 {
2853 case DVR_RECORD_STATE_OPENED:
2854 case DVR_RECORD_STATE_CLOSED:
2855 {
2856 ctx->record.seg_status = evt->record.status;
2857
2858 status.state = evt->record.status.state;
2859 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002860 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002861 } break;
2862 case DVR_RECORD_STATE_STARTED:
2863 {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002864 ctx->record.seg_status = evt->record.status;
2865
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002866 process_generateRecordStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002867 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002868 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002869
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002870 /*restart to next segment*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002871 if (ctx->record.param_open.segment_size
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002872 && evt->record.status.info.size >= ctx->record.param_open.segment_size) {
Wentao MA96f68962022-06-15 19:45:35 +08002873 DVR_WRAPPER_INFO("start new segment for record(%lu), reaches segment size limit, cur(%zu) max(%lld)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002874 ctx->sn,
2875 evt->record.status.info.size,
2876 ctx->record.param_open.segment_size);
Zhiqiang Hand977e972020-05-11 11:30:47 +08002877 if (record_startNextSegment(ctx) != DVR_SUCCESS) {
2878 /*should notify the recording's stop*/
2879 int error = dvr_record_close(ctx->record.recorder);
Wentao MA96f68962022-06-15 19:45:35 +08002880 DVR_WRAPPER_INFO("stop record(%lu)=%d, failed to start new segment for recording.",
Zhiqiang Hand977e972020-05-11 11:30:47 +08002881 ctx->sn, error);
2882 status.state = DVR_RECORD_STATE_CLOSED;
2883 process_notifyRecord(ctx, DVR_RECORD_EVENT_WRITE_ERROR, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002884 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Hand977e972020-05-11 11:30:47 +08002885 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002886 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002887
2888 if (ctx->record.param_open.is_timeshift
2889 && ctx->record.param_open.max_time
2890 && status.info.time >= ctx->record.param_open.max_time) {
Wentao MA270dc0f2022-08-23 13:17:26 +08002891 DVR_WrapperRecordSegmentInfo_t *p_seg;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002892
2893 /*as the player do not support null playlist,
2894 there must be one segment existed at any time,
2895 we have to keep two segments before remove one*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002896 p_seg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
2897 if (p_seg == list_first_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head)) {
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002898 /*only one segment, waiting for more*/
Wentao MA96f68962022-06-15 19:45:35 +08002899 DVR_WRAPPER_INFO("warning: the size(%lld) of max_time(%ld) of record < max size of segment(%lld)\n",
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002900 status.info.size,
2901 ctx->record.param_open.max_time,
2902 ctx->record.param_open.segment_size);
2903 } else {
2904 /*timeshifting, remove the 1st segment and notify the player*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002905 record_removeSegment(ctx, p_seg);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002906
2907 process_generateRecordStatus(ctx, &status);
2908 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002909 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002910 }
2911 }
2912
Wentao MAf4072032022-06-30 13:50:45 +08002913 const loff_t actual_size = status.info.size;
2914 const loff_t max_size = ctx->record.param_open.max_size;
2915 const loff_t segment_size = ctx->record.param_open.segment_size;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002916
Wentao MAf4072032022-06-30 13:50:45 +08002917 if (ctx->record.param_open.is_timeshift && max_size) {
2918 if (actual_size >= max_size) {
Wentao MA270dc0f2022-08-23 13:17:26 +08002919 DVR_WrapperRecordSegmentInfo_t *p_seg;
Wentao MAf4072032022-06-30 13:50:45 +08002920 /*as the player do not support null playlist,
2921 there must be one segment existed at any time,
2922 we have to keep two segments before remove one*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002923 p_seg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
2924 if (p_seg == list_first_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head)) {
Wentao MAf4072032022-06-30 13:50:45 +08002925 /*only one segment, waiting for more*/
2926 DVR_WRAPPER_INFO("warning: the size(%lld) of record < max size of segment(%lld)\n",
2927 actual_size, segment_size);
2928 } else {
Wentao MA270dc0f2022-08-23 13:17:26 +08002929 record_removeSegment(ctx, p_seg);
Wentao MAf4072032022-06-30 13:50:45 +08002930
2931 process_generateRecordStatus(ctx, &status);
2932 process_notifyRecord(ctx, evt->record.event, &status);
2933 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
2934 }
2935 if (actual_size >= max_size + segment_size/2) {
2936 dvr_record_discard_coming_data(ctx->record.recorder,DVR_TRUE);
2937 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002938 } else {
Wentao MAf4072032022-06-30 13:50:45 +08002939 dvr_record_discard_coming_data(ctx->record.recorder,DVR_FALSE);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002940 }
2941 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002942 } break;
2943 case DVR_RECORD_STATE_STOPPED:
2944 {
2945 ctx->record.seg_status = evt->record.status;
2946
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002947 process_generateRecordStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002948 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002949 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002950 } break;
2951 default:
2952 break;
2953 }
2954 } break;
hualing chen4b7c15d2020-04-07 16:13:48 +08002955 case DVR_RECORD_EVENT_WRITE_ERROR: {
2956 ctx->record.seg_status = evt->record.status;
2957 status.state = evt->record.status.state;
2958 process_notifyRecord(ctx, evt->record.event, &status);
2959 }break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002960 default:
2961 break;
2962 }
2963 return DVR_SUCCESS;
2964}
2965
2966static inline int process_notifyPlayback(DVR_WrapperCtx_t *ctx, DVR_PlaybackEvent_t evt, DVR_WrapperPlaybackStatus_t *status)
2967{
Wentao MA80179512022-11-03 12:20:03 +08002968 DVR_RETURN_IF_FALSE(ctx->playback.event_fn != NULL);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002969
Wentao MA80179512022-11-03 12:20:03 +08002970 const time_t cur_time = status->info_cur.time;
2971 const time_t full_time = status->info_full.time;
2972 const time_t obsolete_time = status->info_obsolete.time;
2973 const time_t origin_offset = cur_time + obsolete_time;
2974 DVR_WRAPPER_INFO("playback progress notify(sn:%ld) evt(0x%x)"
2975 " actual_slider_pos: %02d:%02d:%02d.%03d/%02d:%02d:%02d.%03d (%7ld ms/%7ld ms),"
2976 " offset_from_origin: %02d:%02d:%02d.%03d (%7ld ms),"
2977 " dump status:state/cur/full/obsolete(%d/%ld/%ld/%ld)",
2978 ctx->sn,evt,cur_time/1000/3600,cur_time/1000%3600/60,cur_time/1000%60,cur_time%1000,
2979 full_time/1000/3600,full_time/1000%3600/60,full_time/1000%60,full_time%1000,
2980 cur_time,full_time,
2981 origin_offset/1000/3600,origin_offset/1000%3600/60,origin_offset/1000%60,origin_offset%1000,
2982 origin_offset,status->state,cur_time,full_time,obsolete_time);
2983
2984 return ctx->playback.event_fn(evt, status, ctx->playback.event_userdata);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002985}
2986
2987/*should run periodically to update the current status*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002988static int process_generatePlaybackStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperPlaybackStatus_t *status)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002989{
2990 /*the current seg is not covered in the statistics*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002991 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002992
2993 memset(&ctx->playback.status, 0, sizeof(ctx->playback.status));
2994 ctx->playback.status.pids = ctx->playback.pids_req;
2995
2996 ctx->playback.status.state = ctx->playback.seg_status.state;
2997 ctx->playback.status.speed = ctx->playback.seg_status.speed;
2998 ctx->playback.status.flags = ctx->playback.seg_status.flags;
2999 ctx->current_segment_id = ctx->playback.seg_status.segment_id;
3000
wentao.mafd5283f2022-10-14 09:51:13 +08003001 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08003002 // prefetch() here incurring self_assign is used to avoid some compiling
3003 // warnings.
3004 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08003005 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
3006 if (p_seg->seg_info.id == ctx->playback.seg_status.segment_id) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003007 break;
hualing chen451c8f72022-03-09 13:05:52 +08003008 }
3009
Wentao MA270dc0f2022-08-23 13:17:26 +08003010 ctx->playback.status.info_cur.time += p_seg->seg_info.duration;
3011 ctx->playback.status.info_cur.size += p_seg->seg_info.size;
3012 ctx->playback.status.info_cur.pkts += p_seg->seg_info.nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003013 }
wentao.mafd5283f2022-10-14 09:51:13 +08003014 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08003015 // prefetch() here incurring self_assign is used to avoid some compiling
3016 // warnings.
3017 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08003018 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
3019 ctx->playback.status.info_full.time += p_seg->seg_info.duration;
3020 ctx->playback.status.info_full.size += p_seg->seg_info.size;
3021 ctx->playback.status.info_full.pkts += p_seg->seg_info.nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003022 }
3023
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08003024 if (status) {
3025 *status = ctx->playback.status;
3026 /*deal with current, lack size and pkts with the current*/
3027 status->info_cur.time += ctx->playback.seg_status.time_cur;
hualing chen56c0a162022-01-27 17:01:50 +08003028 //get last segment id
Wentao MA270dc0f2022-08-23 13:17:26 +08003029 DVR_WrapperRecordSegmentInfo_t *p_seg;
hualing chen56c0a162022-01-27 17:01:50 +08003030
Wentao MA270dc0f2022-08-23 13:17:26 +08003031 p_seg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
3032 if (ctx->playback.tf_full == DVR_TRUE && p_seg->info.id == ctx->current_segment_id) {
hualing chen56c0a162022-01-27 17:01:50 +08003033 status->disguised_info_obsolete.time = ctx->playback.obsolete.time + ctx->playback.seg_status.time_cur;
3034 status->info_obsolete.time = ctx->playback.obsolete.time;
Wentao MA270dc0f2022-08-23 13:17:26 +08003035 DVR_WRAPPER_INFO("warning change start time :id[%lld] [%d]cur[%d]\n", p_seg->info.id, status->info_obsolete.time, status->info_cur.time);
hualing chen56c0a162022-01-27 17:01:50 +08003036 }
3037 else
3038 {
Wentao MA804bab12022-11-29 10:01:26 +08003039 status->info_obsolete.time = ctx->playback.obsolete.time;
3040 status->disguised_info_obsolete.time = ctx->playback.obsolete.time;
hualing chen56c0a162022-01-27 17:01:50 +08003041 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08003042 }
3043
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003044 return DVR_SUCCESS;
3045}
3046
3047static int process_handlePlaybackEvent(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
3048{
Wentao MA804bab12022-11-29 10:01:26 +08003049 DVR_WRAPPER_DEBUG("evt (sn:%ld) 0x%x (state:%d) cur(%lld:%u/%u)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003050 evt->sn, evt->playback.event,
3051 evt->playback.status.play_status.state,
3052 evt->playback.status.play_status.segment_id,
3053 evt->playback.status.play_status.time_cur,
3054 evt->playback.status.play_status.time_end);
3055
3056 /*evt PLAYTIME will break the last logic, do not save*/
hualing chene3797f02021-01-13 14:53:28 +08003057 if (evt->playback.event != DVR_PLAYBACK_EVENT_NOTIFY_PLAYTIME
3058 && evt->playback.event != DVR_PLAYBACK_EVENT_NODATA
3059 && evt->playback.event != DVR_PLAYBACK_EVENT_DATARESUME
3060 )
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003061 ctx->playback.last_event = evt->playback.event;
3062
3063 switch (evt->playback.event)
3064 {
3065 case DVR_PLAYBACK_EVENT_FIRST_FRAME:
3066 case DVR_PLAYBACK_EVENT_REACHED_END:
3067 case DVR_PLAYBACK_EVENT_TRANSITION_OK:
3068 case DVR_PLAYBACK_EVENT_NOTIFY_PLAYTIME:
hualing chenb5cd42e2020-04-15 17:03:34 +08003069 case DVR_PLAYBACK_EVENT_ERROR:
hualing chenf291cf32020-06-18 10:50:30 +08003070 case DVR_PLAYBACK_EVENT_REACHED_BEGIN:
hualing chene3797f02021-01-13 14:53:28 +08003071 case DVR_PLAYBACK_EVENT_NODATA:
3072 case DVR_PLAYBACK_EVENT_DATARESUME:
Wentao MA9e31f692023-09-26 17:42:18 +08003073 case DVR_PLAYBACK_EVENT_TIMESHIFT_FR_REACHED_BEGIN:
3074 case DVR_PLAYBACK_EVENT_TIMESHIFT_FF_REACHED_END:
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003075 {
3076 DVR_WrapperPlaybackStatus_t status;
3077
3078 /*copy status of segment*/
3079 ctx->playback.seg_status = evt->playback.status.play_status;
3080
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08003081 /*generate status of the whole playback*/
3082 process_generatePlaybackStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003083
3084 if (evt->playback.event == DVR_PLAYBACK_EVENT_REACHED_END) {
Wentao MA96f68962022-06-15 19:45:35 +08003085 DVR_WRAPPER_INFO("playback(sn:%ld) event:0x%x\n", evt->sn, evt->playback.event);
hualing chenb9b358a2021-08-17 15:06:36 +08003086 if (ctx->playback.param_open.is_timeshift
3087 || ctx_isPlay_recording(ctx->playback.param_open.location)) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003088 /*wait for more data in recording*/
Zhiqiang Han31846002021-11-04 10:49:06 +08003089 }
3090 /*trust the low level, make NO check.
3091 As this evt is changed to only once due to some operations(paused) in low level.
3092 else if ((status.info_cur.time + DVR_PLAYBACK_END_GAP) >= ctx->playback.status.info_full.time) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003093 process_notifyPlayback(ctx, evt->playback.event, &status);
Zhiqiang Han31846002021-11-04 10:49:06 +08003094 }
3095 */
3096 else {
3097 process_notifyPlayback(ctx, evt->playback.event, &status);
hualing chenb5cd42e2020-04-15 17:03:34 +08003098 ctx->playback.reach_end = DVR_TRUE;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003099 }
wentao.mab9fe0ff2023-07-05 09:55:41 +08003100 } else {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003101 process_notifyPlayback(ctx, evt->playback.event, &status);
3102 }
3103 } break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003104 case DVR_PLAYBACK_EVENT_TRANSITION_FAILED:
3105 case DVR_PLAYBACK_EVENT_KEY_FAILURE:
3106 case DVR_PLAYBACK_EVENT_NO_KEY:
3107 {
Wentao MA96f68962022-06-15 19:45:35 +08003108 DVR_WRAPPER_INFO("playback(sn:%ld) error event:0x%x\n", evt->sn, evt->playback.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003109 } break;
3110 default:
3111 {
Wentao MA96f68962022-06-15 19:45:35 +08003112 DVR_WRAPPER_INFO("playback(sn:%ld) unknown event:0x%x\n", evt->sn, evt->playback.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003113 } break;
3114 }
3115 return 0;
3116}
3117
3118static inline int process_handleEvents(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
3119{
3120 return (evt->type == W_REC)? process_handleRecordEvent(evt, ctx) : process_handlePlaybackEvent(evt, ctx);
3121}
3122
Wentao MA96f68962022-06-15 19:45:35 +08003123int dvr_wrapper_set_log_level (int level)
3124{
Wentao MA804bab12022-11-29 10:01:26 +08003125 DVR_WRAPPER_INFO("libdvr_api, set_log_level %d", level);
Wentao MA96f68962022-06-15 19:45:35 +08003126 if (level<LOG_LV_DEFAULT || level>LOG_LV_FATAL) {
3127 DVR_WRAPPER_ERROR("Invalid dvr log level:%d", g_dvr_log_level);
3128 return DVR_FAILURE;
3129 }
3130 g_dvr_log_level = level;
3131 DVR_WRAPPER_INFO("New dvr log level:%d", g_dvr_log_level);
3132 return DVR_SUCCESS;
3133}
3134
Wentao MA5629ad82022-08-24 10:03:02 +08003135int dvr_wrapper_set_ac4_preselection_id(DVR_WrapperPlayback_t playback, int presel_id)
3136{
3137 DVR_WrapperCtx_t *ctx;
3138 int error;
3139
Wentao MA3e2dc452022-12-20 11:17:16 +08003140 DVR_RETURN_IF_FALSE(playback!=NULL);
Wentao MA5629ad82022-08-24 10:03:02 +08003141
3142 ctx = ctx_getPlayback((unsigned long)playback);
3143 DVR_RETURN_IF_FALSE(ctx);
3144
3145 wrapper_mutex_lock(&ctx->wrapper_lock);
3146
3147 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
3148
Wentao MA804bab12022-11-29 10:01:26 +08003149 DVR_WRAPPER_INFO("libdvr_api, set_ac4_preselection_id %d", presel_id);
Wentao MA5629ad82022-08-24 10:03:02 +08003150 error = dvr_playback_set_ac4_preselection_id(ctx->playback.player, presel_id);
3151
3152 wrapper_mutex_unlock(&ctx->wrapper_lock);
3153
3154 return error;
3155}
3156
wentao ma7d642782022-10-23 18:26:16 -07003157int dvr_wrapper_property_set(const char* prop_name, const char* prop_value)
3158{
3159 return dvr_prop_write(prop_name,prop_value);
3160}
3161
3162int dvr_wrapper_property_get(const char* prop_name, char* prop_value, int length)
3163{
3164 return dvr_prop_read(prop_name,prop_value,length);
3165}
3166
Zhiqiang Han2f019af2023-08-31 11:12:02 +08003167int dvr_wrapper_ioctl_record(DVR_WrapperRecord_t rec, unsigned int cmd, void *data, size_t size)
3168{
3169 DVR_WrapperCtx_t *ctx;
3170 int error;
3171
3172 DVR_RETURN_IF_FALSE(rec);
3173
3174 ctx = ctx_getRecord((unsigned long)rec);
3175 DVR_RETURN_IF_FALSE(ctx);
3176
3177 wrapper_mutex_lock(&ctx->wrapper_lock);
3178 DVR_WRAPPER_INFO("libdvr_api, ioctl_record (sn:%ld) cmd:%#x data:%p", ctx->sn, cmd, data);
3179 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
3180
3181 error = dvr_record_ioctl(ctx->record.recorder, cmd, data, size);
3182
3183 DVR_WRAPPER_INFO("record(sn:%ld) ioctl_record = (%d)\n", ctx->sn, error);
3184 wrapper_mutex_unlock(&ctx->wrapper_lock);
3185
3186 return error;
3187
3188}