blob: 13dd4086ef5af442a6c522c814584339bba9e6d8 [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>
9#include <time.h>
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080010
11#include "dvr_types.h"
12#include "dvr_record.h"
13#include "dvr_crypto.h"
14#include "dvr_playback.h"
15#include "dvr_segment.h"
16
17#include "AmTsPlayer.h"
18
19#include "list.h"
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080020
21#include "dvr_wrapper.h"
22
Wentao MA96f68962022-06-15 19:45:35 +080023#define WRAPPER_LOG_TAG "libdvr-wrapper"
24#define DVR_WRAPPER_DEBUG(...) DVR_LOG_PRINT(LOG_LV_DEBUG, WRAPPER_LOG_TAG, __VA_ARGS__)
25#define DVR_WRAPPER_INFO(...) DVR_LOG_PRINT(LOG_LV_INFO, WRAPPER_LOG_TAG, __VA_ARGS__)
26#define DVR_WRAPPER_WARN(...) DVR_LOG_PRINT(LOG_LV_WARN, WRAPPER_LOG_TAG, __VA_ARGS__)
27#define DVR_WRAPPER_ERROR(...) DVR_LOG_PRINT(LOG_LV_ERROR, WRAPPER_LOG_TAG, __VA_ARGS__)
28#define DVR_WRAPPER_FATAL(...) DVR_LOG_PRINT(LOG_LV_FATAL, WRAPPER_LOG_TAG, __VA_ARGS__)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080029
30/*duration of data to resume if paused with EVT_REACHED_END in timeshifting*/
hualing chen2932d372020-04-29 13:44:00 +080031#define TIMESHIFT_DATA_DURATION_TO_RESUME (600)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080032/*a tolerant gap*/
33#define DVR_PLAYBACK_END_GAP (1000)
34
Wentao MA96f68962022-06-15 19:45:35 +080035int g_dvr_log_level = LOG_LV_DEFAULT;
36
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080037enum {
38 W_REC = 1,
39 W_PLAYBACK = 2,
40};
41
42enum {
43 U_PIDS = 0x01,
44 U_STAT = 0x02,
45 U_ALL = U_PIDS | U_STAT,
46};
47
48typedef struct {
Gong Kefdb31922022-06-17 17:11:16 +080049 pthread_mutex_t lock;
50 pthread_cond_t cond;
51 int inited;
52 int locked;
53} DVR_WrapperMutex_t;
54
55static void
56wrapper_mutex_init (DVR_WrapperMutex_t *lock)
57{
58 pthread_condattr_t cattr;
59
Zhiqiang Han2259da32022-07-07 15:52:58 +080060 if (lock->inited)
Gong Kefdb31922022-06-17 17:11:16 +080061 return;
62
63 pthread_mutex_init(&lock->lock, NULL);
64
65 pthread_condattr_init(&cattr);
66 pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
67 pthread_cond_init(&lock->cond, &cattr);
68 pthread_condattr_destroy(&cattr);
69
wentao.maa22bc852022-10-13 12:18:06 +080070 // It is not necessary to protect code block below with
71 // DVR_WrapperMutex_t.lock, so the following annotation
72 // is given to surpress related Coverity complaint.
73 // coverity[missing_lock]
Gong Kefdb31922022-06-17 17:11:16 +080074 lock->locked = 0;
75 lock->inited = 1;
76}
77
78static int
79wrapper_mutex_lock (DVR_WrapperMutex_t *lock)
80{
81 pthread_mutex_lock(&lock->lock);
wentao.maa22bc852022-10-13 12:18:06 +080082 // This couldn't be a infinite loop as Coverity reported.
83 // Loop can finish when another thread calls wrapper_mutex_unlock.
84 // coverity[loop_condition]
Gong Kefdb31922022-06-17 17:11:16 +080085 while (lock->locked) {
86 pthread_cond_wait(&lock->cond, &lock->lock);
87 }
88 lock->locked = 1;
89 pthread_mutex_unlock(&lock->lock);
90
91 return 0;
92}
93
94static int
95wrapper_mutex_unlock (DVR_WrapperMutex_t *lock)
96{
97 pthread_mutex_lock(&lock->lock);
98 lock->locked = 0;
99 pthread_mutex_unlock(&lock->lock);
100 pthread_cond_signal(&lock->cond);
101
102 return 0;
103}
104
105static int
106wrapper_mutex_timedlock (DVR_WrapperMutex_t *lock, struct timespec *tv)
107{
108 int r = 0;
109
110 pthread_mutex_lock(&lock->lock);
111 if (lock->locked) {
Zhiqiang Han61ceb3a2022-07-04 17:03:52 +0800112 //DVR_WRAPPER_DEBUG("Enter cond_timedwait");
Gong Kefdb31922022-06-17 17:11:16 +0800113 r = pthread_cond_timedwait(&lock->cond, &lock->lock, tv);
Zhiqiang Han61ceb3a2022-07-04 17:03:52 +0800114 //DVR_WRAPPER_DEBUG("Leave cond_timedwait");
Gong Kefdb31922022-06-17 17:11:16 +0800115 }
116 if (r == 0) {
117 if (!lock->locked) {
118 lock->locked = 1;
119 } else {
120 r = ETIMEDOUT;
121 }
122 }
123 pthread_mutex_unlock(&lock->lock);
124
125 return r;
126}
127
128#define WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(expr, lock)\
129 do {\
130 if (!(expr)) {\
131 DVR_INFO("%s-%d failed", __func__, __LINE__);\
132 wrapper_mutex_unlock(lock);\
133 return DVR_FAILURE;\
134 }\
135 } while (0);
136
137
138typedef struct {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800139 /*make lock the 1st item in the structure*/
Gong Kefdb31922022-06-17 17:11:16 +0800140 DVR_WrapperMutex_t wrapper_lock;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800141
142 /*rec or play*/
143 int type;
144
145 /*valid if (sn != 0)*/
146 unsigned long sn;
147 unsigned long sn_linked;
148
149 struct list_head segments; /**<head-add list*/
150 uint64_t current_segment_id; /**<id of the current segment*/
151
152 union {
153 struct {
154 DVR_WrapperRecordOpenParams_t param_open;
155 DVR_RecordStartParams_t param_start;
156 DVR_RecordStartParams_t param_update;
157 DVR_RecordHandle_t recorder;
158 DVR_RecordEventFunction_t event_fn;
159 void *event_userdata;
160
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800161 /*total status = seg_status + status + obsolete*/
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800162 DVR_RecordStatus_t seg_status; /**<status of current segment*/
163 DVR_WrapperRecordStatus_t status; /**<status of remaining segments*/
164 uint64_t next_segment_id;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800165
166 DVR_WrapperInfo_t obsolete; /**<data obsolete due to the max limit*/
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800167 } record;
168
169 struct {
170 DVR_WrapperPlaybackOpenParams_t param_open;
171 DVR_PlaybackHandle_t player;
172 DVR_PlaybackEventFunction_t event_fn;
173 void *event_userdata;
174
175 /*total status = seg_status + status*/
176 DVR_PlaybackStatus_t seg_status;
177 DVR_WrapperPlaybackStatus_t status;
178 DVR_PlaybackPids_t pids_req;
179 DVR_PlaybackEvent_t last_event;
Zhiqiang Han3eb75f92020-04-08 10:07:55 +0800180 float speed;
hualing chenb5cd42e2020-04-15 17:03:34 +0800181 DVR_Bool_t reach_end;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800182
183 DVR_WrapperInfo_t obsolete;
hualing chen56c0a162022-01-27 17:01:50 +0800184 DVR_Bool_t tf_full;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800185 } playback;
186 };
187} DVR_WrapperCtx_t;
188
189typedef struct {
190 struct list_head head;
191 unsigned long sn;
192
193 /* rec or playback */
194 int type;
195
196 union {
197 struct {
198 DVR_RecordEvent_t event;
199 DVR_RecordStatus_t status;
200 } record;
201 struct {
202 DVR_PlaybackEvent_t event;
203 DVR_Play_Notify_t status;
204 } playback;
205 };
206} DVR_WrapperEventCtx_t;
207
208typedef struct {
209 pthread_mutex_t lock;
210 char *name;
211 int running;
212 pthread_cond_t cond;
213 pthread_t thread;
214 int type;
215} DVR_WrapperThreadCtx_t;
216
217typedef struct {
218 struct list_head head;
219
220 DVR_RecordSegmentInfo_t seg_info;
221 DVR_PlaybackSegmentInfo_t playback_info;
222} DVR_WrapperPlaybackSegmentInfo_t;
223
224typedef struct {
225 struct list_head head;
226
227 DVR_RecordSegmentInfo_t info;
228} DVR_WrapperRecordSegmentInfo_t;
229
230/* serial num generater */
231static unsigned long sn = 1;
232static pthread_mutex_t sn_lock = PTHREAD_MUTEX_INITIALIZER;
233
234static inline unsigned long get_sn()
235{
hualing chenab0d1262021-09-26 15:22:50 +0800236 unsigned long no = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800237
238 pthread_mutex_lock(&sn_lock);
239 no = sn++;
240 if (!no)
241 no = sn++;
242 pthread_mutex_unlock(&sn_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800243 return no;
244}
245
246/* entity ctx */
247#define DVR_WRAPPER_MAX 10
248
249static DVR_WrapperCtx_t record_list[DVR_WRAPPER_MAX] =
250{
251 [0 ... (DVR_WRAPPER_MAX - 1)] =
252 {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800253 .type = W_REC,
254 }
255};
256
257static DVR_WrapperCtx_t playback_list[DVR_WRAPPER_MAX] =
258{
259 [0 ... (DVR_WRAPPER_MAX - 1)] =
260 {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800261 .type = W_PLAYBACK,
262 }
263};
264
265/* events lists */
266static struct list_head record_evt_list = LIST_HEAD_INIT(record_evt_list);
267static struct list_head playback_evt_list = LIST_HEAD_INIT(playback_evt_list);
268
269static pthread_mutex_t record_evt_list_lock = PTHREAD_MUTEX_INITIALIZER;
270static pthread_mutex_t playback_evt_list_lock = PTHREAD_MUTEX_INITIALIZER;
271
272static DVR_WrapperThreadCtx_t wrapper_thread[2] =
273{
274 [0] =
275 {
276 .lock = PTHREAD_MUTEX_INITIALIZER,
277 .running = 0,
278 .name = "record",
279 .type = W_REC,
280 },
281 [1] =
282 {
283 .lock = PTHREAD_MUTEX_INITIALIZER,
284 .running = 0,
285 .name = "playback",
286 .type = W_PLAYBACK,
287 },
288};
289
290/*now only support one timeshift now*/
291static unsigned long sn_timeshift_record;
292static unsigned long sn_timeshift_playback;
293
294static void *wrapper_task(void *arg);
295static inline int process_handleEvents(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx);
296
297static DVR_Result_t wrapper_record_event_handler(DVR_RecordEvent_t event, void *params, void *userdata);
298static DVR_Result_t wrapper_playback_event_handler(DVR_PlaybackEvent_t event, void *params, void *userdata);
299
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800300static int process_generateRecordStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordStatus_t *status);
301static int process_generatePlaybackStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperPlaybackStatus_t *status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800302
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800303static int get_timespec_timeout(int timeout, struct timespec *ts)
304{
305 struct timespec ots;
306 int left, diff;
307
308 clock_gettime(CLOCK_MONOTONIC, &ots);
309
310 ts->tv_sec = ots.tv_sec + timeout / 1000;
311 ts->tv_nsec = ots.tv_nsec;
312
313 left = timeout % 1000;
314 left *= 1000000;
315 diff = 1000000000 - ots.tv_nsec;
316
317 if (diff <= left) {
318 ts->tv_sec++;
319 ts->tv_nsec = left-diff;
320 } else {
321 ts->tv_nsec += left;
322 }
323
324 return 0;
325}
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800326
327static DVR_WrapperEventCtx_t *ctx_getEvent(struct list_head *list, pthread_mutex_t *list_lock)
328{
Wentao MA270dc0f2022-08-23 13:17:26 +0800329 DVR_WrapperEventCtx_t *p_evt;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800330
331 pthread_mutex_lock(list_lock);
332 if (list_empty(list))
Wentao MA270dc0f2022-08-23 13:17:26 +0800333 p_evt = NULL;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800334 else {
Wentao MA270dc0f2022-08-23 13:17:26 +0800335 p_evt = list_first_entry(list, DVR_WrapperEventCtx_t, head);
336 list_del(&p_evt->head);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800337 }
338 pthread_mutex_unlock(list_lock);
339
Wentao MA270dc0f2022-08-23 13:17:26 +0800340 return p_evt;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800341}
342
343static inline DVR_WrapperEventCtx_t *ctx_getRecordEvent()
344{
345 return ctx_getEvent(&record_evt_list, &record_evt_list_lock);
346}
347
348static inline DVR_WrapperEventCtx_t *ctx_getPlaybackEvent()
349{
350 return ctx_getEvent(&playback_evt_list, &playback_evt_list_lock);
351}
352
353static int ctx_addEvent(struct list_head *list, pthread_mutex_t *lock, DVR_WrapperEventCtx_t *evt)
354{
355 DVR_WrapperEventCtx_t *padd;
356 padd = (DVR_WrapperEventCtx_t *)calloc(1, sizeof(DVR_WrapperEventCtx_t));
357 DVR_RETURN_IF_FALSE(padd);
358
359 *padd = *evt;
360 pthread_mutex_lock(lock);
wentao.maa22bc852022-10-13 12:18:06 +0800361 list_add_tail(padd, list);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800362 pthread_mutex_unlock(lock);
363 return DVR_SUCCESS;
364}
365
366static inline void ctx_freeEvent(DVR_WrapperEventCtx_t *evt)
367{
368 free(evt);
369}
370
371/*useless*/
372static void ctx_cleanOutdatedEvents(struct list_head *evt_list,
373 pthread_mutex_t *evt_list_lock,
374 DVR_WrapperCtx_t *list)
375{
Wentao MA270dc0f2022-08-23 13:17:26 +0800376 DVR_WrapperEventCtx_t *p_evt, *p_evt_tmp;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800377 unsigned long sns[DVR_WRAPPER_MAX];
378 int cnt = 0;
379 int i;
380 int found = 0;
381
382 /*copy all valid sns*/
383 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
384 sns[cnt] = list[i].sn;
385 if (!sns[cnt])
386 cnt++;
387 }
388
389 /*free evts that not belong to any valid sns*/
390 pthread_mutex_lock(evt_list_lock);
Wentao MA270dc0f2022-08-23 13:17:26 +0800391 list_for_each_entry_safe(p_evt, p_evt_tmp, evt_list, head) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800392 for (i = 0; i < cnt; i++) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800393 if (p_evt->sn == sns[i]) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800394 found = 1;
395 break;
396 }
397 }
398 if (!found) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800399 list_del(&p_evt->head);
400 ctx_freeEvent(p_evt);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800401 }
402 }
403 pthread_mutex_unlock(evt_list_lock);
404}
405
406static inline void ctx_cleanOutdatedRecordEvents()
407{
408 ctx_cleanOutdatedEvents(&record_evt_list, &record_evt_list_lock, record_list);
409}
410
411static inline void ctx_cleanOutdatedPlaybackEvents()
412{
413 ctx_cleanOutdatedEvents(&playback_evt_list, &playback_evt_list_lock, playback_list);
414}
415
hualing chenb9b358a2021-08-17 15:06:36 +0800416//check this play is recording file
417//return 0 if not the recording
418//else return record id
419static inline int ctx_isPlay_recording(char *play_location)
420{
421 int i;
422 DVR_WrapperCtx_t *cnt;
423
424 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
425 cnt = &record_list[i];
Wentao MA96f68962022-06-15 19:45:35 +0800426 //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 +0800427 if (!strcmp(cnt->record.param_open.location, play_location)) {
Wentao MA96f68962022-06-15 19:45:35 +0800428 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 +0800429 return cnt->sn;
430 }
431 }
Wentao MA270dc0f2022-08-23 13:17:26 +0800432 DVR_WRAPPER_INFO(" not found any play is in recording [%d]", DVR_WRAPPER_MAX);
hualing chenb9b358a2021-08-17 15:06:36 +0800433 return 0;
434}
435//check this record is playing file
436//return 0 if not the playing
437//else return playback id
438static inline int ctx_isRecord_playing(char *rec_location)
439{
440 int i;
441 DVR_WrapperCtx_t *cnt;
442 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
443 cnt = &playback_list[i];
Wentao MA96f68962022-06-15 19:45:35 +0800444 //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 +0800445 if (!strcmp(cnt->playback.param_open.location, rec_location)) {
Wentao MA96f68962022-06-15 19:45:35 +0800446 DVR_WRAPPER_INFO("[%d]sn[%d]P[%s]R[%s] ..found.\n",i, cnt->sn, cnt->playback.param_open.location, rec_location);
hualing chenb9b358a2021-08-17 15:06:36 +0800447 return cnt->sn;
448 }
449 }
Wentao MA96f68962022-06-15 19:45:35 +0800450 DVR_WRAPPER_INFO(" not found rec is playing [%d]", DVR_WRAPPER_MAX);
hualing chenb9b358a2021-08-17 15:06:36 +0800451 return 0;
452}
453
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800454static inline DVR_WrapperCtx_t *ctx_get(unsigned long sn, DVR_WrapperCtx_t *list)
455{
456 int i;
457 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
Gong Kefdb31922022-06-17 17:11:16 +0800458 if (list[i].sn == sn) {
459 wrapper_mutex_init(&list[i].wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800460 return &list[i];
Gong Kefdb31922022-06-17 17:11:16 +0800461 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800462 }
463 return NULL;
464}
465
466static inline void ctx_reset(DVR_WrapperCtx_t *ctx)
467{
468 memset((char *)ctx + offsetof(DVR_WrapperCtx_t, sn),
469 0,
470 sizeof(DVR_WrapperCtx_t) - offsetof(DVR_WrapperCtx_t, sn));
471}
472
473static inline int ctx_valid(DVR_WrapperCtx_t *ctx)
474{
475 return (ctx->sn != 0);
476}
477
478static inline DVR_WrapperCtx_t *ctx_getRecord(unsigned long sn)
479{
480 return ctx_get(sn, record_list);
481}
482
483static inline DVR_WrapperCtx_t *ctx_getPlayback(unsigned long sn)
484{
485 return ctx_get(sn, playback_list);
486}
487
488static int wrapper_requestThread(DVR_WrapperThreadCtx_t *ctx, void *(thread_fn)(void *))
489{
490 pthread_mutex_lock(&ctx->lock);
491 if (ctx->running == 0) {
wentao.maa210e5e2022-10-12 16:10:03 +0800492 pthread_condattr_t attr = {0};
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800493 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
494 pthread_cond_init(&ctx->cond, &attr);
495 pthread_condattr_destroy(&attr);
Wentao MA96f68962022-06-15 19:45:35 +0800496 DVR_WRAPPER_INFO("start wrapper thread(%s) ...\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800497 pthread_create(&ctx->thread, NULL, thread_fn, ctx);
Wentao MA96f68962022-06-15 19:45:35 +0800498 DVR_WRAPPER_INFO("wrapper thread(%s) started\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800499 }
500 ctx->running++;
501 pthread_mutex_unlock(&ctx->lock);
502 return 0;
503}
504
505static int wrapper_releaseThread(DVR_WrapperThreadCtx_t *ctx)
506{
507 pthread_mutex_lock(&ctx->lock);
508 ctx->running--;
509 if (!ctx->running) {
510 pthread_cond_broadcast(&ctx->cond);
511 pthread_mutex_unlock(&ctx->lock);
512
Wentao MA96f68962022-06-15 19:45:35 +0800513 DVR_WRAPPER_INFO("stop wrapper thread(%s) ...\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800514 pthread_join(ctx->thread, NULL);
Wentao MA96f68962022-06-15 19:45:35 +0800515 DVR_WRAPPER_INFO("wrapper thread(%s) stopped\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800516
517 pthread_mutex_lock(&ctx->lock);
518 if (!ctx->running) /*protect*/
519 pthread_cond_destroy(&ctx->cond);
520 }
521 pthread_mutex_unlock(&ctx->lock);
522 return 0;
523}
524
525#define WRAPPER_THREAD_RECORD (&wrapper_thread[0])
526#define WRAPPER_THREAD_PLAYBACK (&wrapper_thread[1])
527
528static inline int wrapper_requestThreadFor(DVR_WrapperCtx_t *ctx)
529{
530 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC)?
531 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
532 return wrapper_requestThread(thread_ctx, wrapper_task);
533}
534
535static inline int wrapper_releaseThreadFor(DVR_WrapperCtx_t *ctx)
536{
537 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC)?
538 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
539 return wrapper_releaseThread(thread_ctx);
540}
541
542static inline int wrapper_releaseThreadForType(int type)
543{
544 DVR_WrapperThreadCtx_t *thread_ctx = (type == W_REC)?
545 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
546 return wrapper_releaseThread(thread_ctx);
547}
548
549static inline void wrapper_threadSignal(DVR_WrapperThreadCtx_t *thread_ctx)
550{
551 pthread_cond_signal(&thread_ctx->cond);
552}
553
554static inline int wrapper_threadWait(DVR_WrapperThreadCtx_t *thread_ctx)
555{
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800556 struct timespec rt;
557 get_timespec_timeout(200, &rt);
558 pthread_cond_timedwait(&thread_ctx->cond, &thread_ctx->lock, &rt);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800559 return 0;
560}
561
562static inline void wrapper_threadSignalForType(int type)
563{
564 DVR_WrapperThreadCtx_t *thread_ctx = (type == W_REC) ?
565 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
566 wrapper_threadSignal(thread_ctx);
567}
568
569static inline void wrapper_threadSignalFor(DVR_WrapperCtx_t *ctx)
570{
571 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC) ?
572 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
573 wrapper_threadSignal(thread_ctx);
574}
575
576static inline int wrapper_threadWaitFor(DVR_WrapperCtx_t *ctx)
577{
578 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC) ?
579 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
580 wrapper_threadWait(thread_ctx);
581 return 0;
582}
583
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800584/*return condition, locked if condition == true*/
Gong Kefdb31922022-06-17 17:11:16 +0800585static int wrapper_mutex_lock_if(DVR_WrapperMutex_t *lock, int *condition)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800586{
587 int r2;
588 do {
589 struct timespec rt2;
Gong Kefdb31922022-06-17 17:11:16 +0800590 get_timespec_timeout(10, &rt2);
591 r2 = wrapper_mutex_timedlock(lock, &rt2);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800592 } while (*condition && (r2 == ETIMEDOUT));
593
594 if (!(*condition) && (r2 == 0))
Gong Kefdb31922022-06-17 17:11:16 +0800595 wrapper_mutex_unlock(lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800596
597 return *condition;
598}
599
600static void *wrapper_task(void *arg)
601{
Wentao MA270dc0f2022-08-23 13:17:26 +0800602 DVR_WrapperThreadCtx_t *thread_ctx = (DVR_WrapperThreadCtx_t *)arg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800603 DVR_WrapperEventCtx_t *evt;
604
Wentao MA270dc0f2022-08-23 13:17:26 +0800605 pthread_mutex_lock(&thread_ctx->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800606
Wentao MA270dc0f2022-08-23 13:17:26 +0800607 while (thread_ctx->running) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800608 {
609 int ret;
hualing chene3797f02021-01-13 14:53:28 +0800610
Wentao MA270dc0f2022-08-23 13:17:26 +0800611 evt = (thread_ctx->type == W_REC)? ctx_getRecordEvent() : ctx_getPlaybackEvent();
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800612 if (!evt)
Wentao MA270dc0f2022-08-23 13:17:26 +0800613 ret = wrapper_threadWait(thread_ctx);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800614 }
615
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800616 while (evt) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800617 DVR_WrapperCtx_t *ctx = (evt->type == W_REC)?
618 ctx_getRecord(evt->sn) : ctx_getPlayback(evt->sn);
hualing chenbc0aec92021-03-18 14:52:40 +0800619 if (ctx == NULL) {
Wentao MA96f68962022-06-15 19:45:35 +0800620 DVR_WRAPPER_INFO("warp not get ctx.free event..\n");
hualing chenbc0aec92021-03-18 14:52:40 +0800621 goto processed;
622 }
Wentao MA270dc0f2022-08-23 13:17:26 +0800623 DVR_WRAPPER_INFO("start name(%s) sn(%d) running(%d) type(%d)\n", thread_ctx->name, (int)ctx->sn, thread_ctx->running, thread_ctx->type);
624 if (thread_ctx->running) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800625 /*
626 continue not break,
627 make all events consumed, or mem leak
628 */
Wentao MA270dc0f2022-08-23 13:17:26 +0800629 if (!wrapper_mutex_lock_if(&ctx->wrapper_lock, &thread_ctx->running))
Zhiqiang Hanef61c0a2020-04-13 15:49:24 +0800630 goto processed;
631
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800632 if (ctx_valid(ctx)) {
633 /*double check after lock*/
Zhiqiang Han3b9c9082021-11-10 10:41:09 +0800634 if (evt->sn == ctx->sn) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800635 pthread_mutex_unlock(&thread_ctx->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800636 process_handleEvents(evt, ctx);
Wentao MA270dc0f2022-08-23 13:17:26 +0800637 pthread_mutex_lock(&thread_ctx->lock);
Zhiqiang Han3b9c9082021-11-10 10:41:09 +0800638 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800639 }
Gong Kefdb31922022-06-17 17:11:16 +0800640 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800641 }
642
Zhiqiang Hanef61c0a2020-04-13 15:49:24 +0800643processed:
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800644 ctx_freeEvent(evt);
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800645
Wentao MA270dc0f2022-08-23 13:17:26 +0800646 evt = (thread_ctx->type == W_REC)? ctx_getRecordEvent() : ctx_getPlaybackEvent();
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800647 }
Wentao MA270dc0f2022-08-23 13:17:26 +0800648 DVR_WRAPPER_INFO("start name(%s) running(%d) type(%d) con...\n", thread_ctx->name, thread_ctx->running, thread_ctx->type);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800649 }
650
Wentao MA270dc0f2022-08-23 13:17:26 +0800651 pthread_mutex_unlock(&thread_ctx->lock);
652 DVR_WRAPPER_INFO("end name(%s) running(%d) type(%d) end...\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)
669 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.maa22bc852022-10-13 12:18:06 +0800732 // This error is surpressed as the macro code is picked from kernel.
733 // 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
752 && (seg_info->duration >= ((time_t)ctx->playback.seg_status.time_cur + TIMESHIFT_DATA_DURATION_TO_RESUME)))
753 ||
754 /*or there's a new segment and has $TIMESHIFT_DATA_DURATION_TO_RESUME of data*/
755 (ctx->playback.seg_status.segment_id != seg_info->id
756 && (seg_info->duration >= TIMESHIFT_DATA_DURATION_TO_RESUME))
757 )
758 {
759 int error;
hualing chen36e0dfd2020-05-02 16:33:06 +0800760 //clear end event
Zhiqiang Hanb723cdb2020-05-09 11:10:29 +0800761 if (ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_END)
hualing chen36e0dfd2020-05-02 16:33:06 +0800762 ctx->playback.last_event = DVR_PLAYBACK_EVENT_TRANSITION_OK;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800763
764 error = dvr_playback_resume(ctx->playback.player);
Wentao MA96f68962022-06-15 19:45:35 +0800765 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 +0800766 ctx->sn, error,
767 seg_info->id, seg_info->duration,
768 ctx->playback.seg_status.segment_id, ctx->playback.seg_status.time_cur);
769 }
770 }
771
772 return DVR_SUCCESS;
773}
774
Wentao MA270dc0f2022-08-23 13:17:26 +0800775static void _updateRecordSegment(DVR_WrapperRecordSegmentInfo_t *p_seg,
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800776 DVR_RecordSegmentInfo_t *seg_info, int update_flags, DVR_WrapperCtx_t *ctx)
777{
778 (void)ctx;
779 if ((update_flags & U_PIDS) && (update_flags & U_STAT))
Wentao MA270dc0f2022-08-23 13:17:26 +0800780 p_seg->info = *seg_info;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800781 else if (update_flags & U_PIDS) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800782 p_seg->info.nb_pids = seg_info->nb_pids;
783 memcpy(p_seg->info.pids, seg_info->pids, sizeof(p_seg->info.pids));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800784 } else if (update_flags & U_STAT) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800785 p_seg->info.duration = seg_info->duration;
786 p_seg->info.size = seg_info->size;
787 p_seg->info.nb_packets = seg_info->nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800788 }
789}
790
791static int wrapper_updateRecordSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info, int update_flags)
792{
Wentao MA270dc0f2022-08-23 13:17:26 +0800793 DVR_WrapperRecordSegmentInfo_t *p_seg = NULL;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800794
795 /*normally, the last segment added will be updated*/
hualing chen266b9502020-04-04 17:39:39 +0800796 if (!list_empty(&ctx->segments)) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800797 p_seg =
hualing chen266b9502020-04-04 17:39:39 +0800798 list_first_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
Wentao MA270dc0f2022-08-23 13:17:26 +0800799 if (p_seg->info.id == seg_info->id) {
800 _updateRecordSegment(p_seg, seg_info, update_flags, ctx);
hualing chen266b9502020-04-04 17:39:39 +0800801 } else {
wentao.maa22bc852022-10-13 12:18:06 +0800802 // This error is surpressed as the macro code is picked from kernel.
803 // prefetch() here incurring self_assign is used to avoid some compiling
804 // warnings.
805 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +0800806 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
807 if (p_seg->info.id == seg_info->id) {
808 _updateRecordSegment(p_seg, seg_info, update_flags, ctx);
hualing chen266b9502020-04-04 17:39:39 +0800809 break;
810 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800811 }
812 }
813 }
814
815 /*timeshift, update the segment for playback*/
816 /*
817 the playback should grab the segment info other than the id,
818 and the id will be updated by each segment-add during the recording
819 */
820 /*
821 the playback paused if no data been checked from recording,
822 should resume the player later when there's more data
823 */
hualing chenb9b358a2021-08-17 15:06:36 +0800824 int sn = 0;
825 if (ctx->record.param_open.is_timeshift ||
826 (sn = ctx_isRecord_playing(ctx->record.param_open.location))) {
827 DVR_WrapperCtx_t *ctx_playback;
828 if (ctx->record.param_open.is_timeshift)
829 ctx_playback = ctx_getPlayback(sn_timeshift_playback);
830 else
831 ctx_playback = ctx_getPlayback(sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800832
833 if (ctx_playback) {
Gong Kefdb31922022-06-17 17:11:16 +0800834 wrapper_mutex_lock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800835 if (ctx_valid(ctx_playback)
hualing chenb9b358a2021-08-17 15:06:36 +0800836 && (ctx_playback->sn == sn_timeshift_playback ||
837 ctx_playback->sn == sn)) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800838 wrapper_updatePlaybackSegment(ctx_playback, seg_info, update_flags);
839 }
Gong Kefdb31922022-06-17 17:11:16 +0800840 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800841 }
842 }
843
844 return DVR_SUCCESS;
845}
846
847static int wrapper_addPlaybackSegment(DVR_WrapperCtx_t *ctx,
848 DVR_RecordSegmentInfo_t *seg_info,
849 DVR_PlaybackPids_t *p_pids,
850 DVR_PlaybackSegmentFlag_t flags)
851{
Wentao MA270dc0f2022-08-23 13:17:26 +0800852 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800853 int error;
854
855 error = 0;
Wentao MA270dc0f2022-08-23 13:17:26 +0800856 p_seg = (DVR_WrapperPlaybackSegmentInfo_t *)calloc(1, sizeof(DVR_WrapperPlaybackSegmentInfo_t));
857 if (!p_seg) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800858 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +0800859 DVR_WRAPPER_INFO("memory fail\n");
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800860 return error;
861 }
862
Wentao MA270dc0f2022-08-23 13:17:26 +0800863 /*copy the original segment info*/
864 p_seg->seg_info = *seg_info;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800865 /*generate the segment info used in playback*/
Wentao MA270dc0f2022-08-23 13:17:26 +0800866 p_seg->playback_info.segment_id = p_seg->seg_info.id;
Wentao MAe88ad702022-09-02 10:35:00 +0800867 const int len = strlen(ctx->playback.param_open.location);
868 if (len >= DVR_MAX_LOCATION_SIZE || len <= 0) {
869 DVR_WRAPPER_ERROR("Invalid playback.param_open.location length %d", len);
Wentao MA4d85ff32022-09-23 11:36:18 +0800870 free(p_seg);
Wentao MAe88ad702022-09-02 10:35:00 +0800871 return DVR_FAILURE;
872 }
873 strncpy(p_seg->playback_info.location, ctx->playback.param_open.location, len+1);
Wentao MA270dc0f2022-08-23 13:17:26 +0800874 p_seg->playback_info.pids = *p_pids;
875 p_seg->playback_info.flags = flags;
Wentao MA270dc0f2022-08-23 13:17:26 +0800876 p_seg->playback_info.duration = p_seg->seg_info.duration;
wentao.maa22bc852022-10-13 12:18:06 +0800877 list_add(p_seg, &ctx->segments);
878 DVR_WRAPPER_INFO("start to add segment %lld\n", p_seg->playback_info.segment_id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800879
Wentao MA270dc0f2022-08-23 13:17:26 +0800880 error = dvr_playback_add_segment(ctx->playback.player, &p_seg->playback_info);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800881 if (error) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800882 DVR_WRAPPER_INFO("fail to add segment %lld (%d)\n", p_seg->playback_info.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800883 } else {
Wentao MA270dc0f2022-08-23 13:17:26 +0800884 ctx->playback.status.info_full.time += p_seg->seg_info.duration;
885 ctx->playback.status.info_full.size += p_seg->seg_info.size;
886 ctx->playback.status.info_full.pkts += p_seg->seg_info.nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800887 }
888
889 return error;
890}
891
892static int wrapper_addRecordSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info)
893{
Wentao MA270dc0f2022-08-23 13:17:26 +0800894 DVR_WrapperRecordSegmentInfo_t *p_seg;
Wentao MA16f870e2022-09-09 11:00:22 +0800895 int error = DVR_SUCCESS;
hualing chenab0d1262021-09-26 15:22:50 +0800896 int sn = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800897
Wentao MA270dc0f2022-08-23 13:17:26 +0800898 p_seg = (DVR_WrapperRecordSegmentInfo_t *)calloc(1, sizeof(DVR_WrapperRecordSegmentInfo_t));
899 if (!p_seg) {
Wentao MA16f870e2022-09-09 11:00:22 +0800900 DVR_WRAPPER_ERROR("memory allocation failed");
901 return DVR_FAILURE;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800902 }
Wentao MA270dc0f2022-08-23 13:17:26 +0800903 p_seg->info = *seg_info;
wentao.maa22bc852022-10-13 12:18:06 +0800904 list_add(p_seg, &ctx->segments);
hualing chenab0d1262021-09-26 15:22:50 +0800905
hualing chenb9b358a2021-08-17 15:06:36 +0800906 if (ctx->record.param_open.is_timeshift ||
907 (sn = ctx_isRecord_playing(ctx->record.param_open.location))) {
908
909 DVR_WrapperCtx_t *ctx_playback;
910 if (ctx->record.param_open.is_timeshift)
911 ctx_playback = ctx_getPlayback(sn_timeshift_playback);
912 else
913 ctx_playback = ctx_getPlayback(sn);
914
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800915 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: playback(sn:%ld) add seg\n", ctx->sn, sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800916
917 if (ctx_playback) {
Gong Kefdb31922022-06-17 17:11:16 +0800918 wrapper_mutex_lock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800919 if (ctx_valid(ctx_playback)) {
920 DVR_PlaybackSegmentFlag_t flags;
921
922 /*only if playback has started, the previous segments have been loaded*/
923 if (!list_empty(&ctx_playback->segments)) {
924 flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
Gong Ke2a0ebbe2021-05-25 15:22:50 +0800925 if (ctx->record.param_open.flags & DVR_RECORD_FLAG_SCRAMBLED)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800926 flags |= DVR_PLAYBACK_SEGMENT_ENCRYPTED;
wentao.maa210e5e2022-10-12 16:10:03 +0800927 error = wrapper_addPlaybackSegment(ctx_playback, seg_info, &ctx_playback->playback.pids_req, flags);
928 if (error == DVR_FAILURE) {
929 DVR_WRAPPER_WARN("adding playback segment fails");
930 }
hualing chen451c8f72022-03-09 13:05:52 +0800931 } else {
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800932 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: playback(sn:%ld) list empty\n", ctx->sn, sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800933 }
hualing chenb9b358a2021-08-17 15:06:36 +0800934 } else {
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800935 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: playback(sn:%ld) not valid\n", ctx->sn, sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800936 }
Gong Kefdb31922022-06-17 17:11:16 +0800937 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800938 }
hualing chen451c8f72022-03-09 13:05:52 +0800939 else
940 {
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800941 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: playback(sn:%ld) not valid 2\n", ctx->sn, sn);
942 }
943
944 /*if it is not a timeshift recording, but a playing recording,
945 do not forget to obey the recording rule: link the segment!*/
946 if (!ctx->record.param_open.is_timeshift) {
947 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: update link\n", ctx->sn);
948 dvr_segment_link_op(ctx->record.param_open.location, 1, &seg_info->id, SEGMENT_OP_ADD);
hualing chen451c8f72022-03-09 13:05:52 +0800949 }
Zhiqiang Hane0a1c382021-06-08 11:28:05 +0800950 } else {
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800951 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: update link\n", ctx->sn);
Wentao MAe8ba5172022-08-09 11:18:17 +0800952 dvr_segment_link_op(ctx->record.param_open.location, 1, &seg_info->id, SEGMENT_OP_ADD);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800953 }
954
955 return error;
956}
957
958static int wrapper_removePlaybackSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info)
959{
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800960 int error = -1;
Wentao MA270dc0f2022-08-23 13:17:26 +0800961 DVR_WrapperPlaybackSegmentInfo_t *p_seg = NULL, *p_seg_tmp;
hualing chenb9a1a2c2021-12-31 11:27:59 +0800962 uint32_t off_set = 0;
Wentao MA96f68962022-06-15 19:45:35 +0800963 DVR_WRAPPER_INFO("timeshift, remove playback(sn:%ld) segment(%lld) ...\n", ctx->sn, seg_info->id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800964
Wentao MA270dc0f2022-08-23 13:17:26 +0800965 list_for_each_entry_safe_reverse(p_seg, p_seg_tmp, &ctx->segments, head) {
966 if (p_seg->seg_info.id == seg_info->id) {
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800967
968 if (ctx->current_segment_id == seg_info->id) {
969 DVR_WrapperPlaybackSegmentInfo_t *next_seg;
970
971 /*drive the player out of this will-be-deleted segment*/
Wentao MA270dc0f2022-08-23 13:17:26 +0800972 next_seg = list_prev_entry(p_seg, head);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800973
974 if (ctx->playback.speed != 100.0f) {
975 error = dvr_playback_resume(ctx->playback.player);
Wentao MA96f68962022-06-15 19:45:35 +0800976 DVR_WRAPPER_INFO("timeshift, playback(sn:%ld), resume for new start (%d)\n", ctx->sn, error);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800977 }
hualing chenb9a1a2c2021-12-31 11:27:59 +0800978 if (ctx->playback.param_open.vendor == DVR_PLAYBACK_VENDOR_AMAZON)
979 off_set = 10 * 1000;
980 error = dvr_playback_seek(ctx->playback.player, next_seg->seg_info.id, off_set);
Wentao MA96f68962022-06-15 19:45:35 +0800981 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 +0800982
983 if (ctx->playback.speed == 0.0f) {
984 error = dvr_playback_pause(ctx->playback.player, DVR_FALSE);
Wentao MA96f68962022-06-15 19:45:35 +0800985 DVR_WRAPPER_INFO("timeshift, playback(sn:%ld), keep last paused from new start (%d)\n", ctx->sn, error);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800986 } else if (ctx->playback.speed != 100.0f) {
987 DVR_PlaybackSpeed_t dvr_speed = {
988 .speed = { ctx->playback.speed },
989 .mode = ( ctx->playback.speed > 0) ? DVR_PLAYBACK_FAST_FORWARD : DVR_PLAYBACK_FAST_BACKWARD
990 };
991 error = dvr_playback_set_speed(ctx->playback.player, dvr_speed);
Wentao MA96f68962022-06-15 19:45:35 +0800992 DVR_WRAPPER_INFO("timeshift, playback(sn:%ld), keep last speed(x%f) from new start (%d)\n", ctx->sn,ctx->playback.speed, error);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800993 }
994 }
995
996 error = dvr_playback_remove_segment(ctx->playback.player, seg_info->id);
997 if (error) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800998 /*remove playback segment fail*/
Wentao MA96f68962022-06-15 19:45:35 +0800999 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 +08001000 }
1001
Wentao MA270dc0f2022-08-23 13:17:26 +08001002 list_del(&p_seg->head);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001003
1004 /*record the obsolete*/
Wentao MA270dc0f2022-08-23 13:17:26 +08001005 ctx->playback.obsolete.time += p_seg->seg_info.duration;
1006 ctx->playback.obsolete.size += p_seg->seg_info.size;
1007 ctx->playback.obsolete.pkts += p_seg->seg_info.nb_packets;
Wentao MA96f68962022-06-15 19:45:35 +08001008 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 +08001009 dvr_playback_set_obsolete(ctx->playback.player, ctx->playback.obsolete.time);
Wentao MA270dc0f2022-08-23 13:17:26 +08001010 free(p_seg);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001011 break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001012 }
1013 }
1014
Wentao MA96f68962022-06-15 19:45:35 +08001015 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 +08001016
1017 return error;
1018}
1019
1020static int wrapper_removeRecordSegment(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordSegmentInfo_t *seg_info)
1021{
1022 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08001023 DVR_WrapperRecordSegmentInfo_t *p_seg, *p_seg_tmp;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001024
Wentao MAf4072032022-06-30 13:50:45 +08001025 DVR_WRAPPER_INFO("calling %s on record(sn:%ld) segment(%lld) ...",
1026 __func__, ctx->sn, seg_info->info.id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001027
1028 /*if timeshifting, notify the playback first, then deal with record*/
1029 if (ctx->record.param_open.is_timeshift) {
1030 DVR_WrapperCtx_t *ctx_playback = ctx_getPlayback(sn_timeshift_playback);
1031
1032 if (ctx_playback) {
Gong Kefdb31922022-06-17 17:11:16 +08001033 wrapper_mutex_lock(&ctx_playback->wrapper_lock);
hualing chen56c0a162022-01-27 17:01:50 +08001034 if (ctx_playback->current_segment_id == seg_info->info.id && ctx_playback->playback.speed == 100.0f) {
1035 ctx_playback->playback.tf_full = DVR_TRUE;
Wentao MAf4072032022-06-30 13:50:45 +08001036 DVR_WRAPPER_INFO("%s, cannot remove record(sn:%ld) segment(%lld) for it is being"
1037 " played on segment(%lld) at speed %f.", __func__, ctx->sn, seg_info->info.id,
1038 ctx_playback->current_segment_id, ctx_playback->playback.speed);
Gong Kefdb31922022-06-17 17:11:16 +08001039 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
hualing chen56c0a162022-01-27 17:01:50 +08001040 return DVR_SUCCESS;
1041 } else {
Wentao MAf4072032022-06-30 13:50:45 +08001042 DVR_WRAPPER_INFO("%s, removing record(sn:%ld) segment(%lld) which is being played "
1043 "on segment (%lld) at speed (%f).", __func__, ctx->sn, seg_info->info.id,
1044 ctx_playback->current_segment_id,ctx_playback->playback.speed);
hualing chen56c0a162022-01-27 17:01:50 +08001045 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001046 if (ctx_valid(ctx_playback)
1047 && ctx_playback->sn == sn_timeshift_playback
1048 && !list_empty(&ctx_playback->segments)) {
1049 error = wrapper_removePlaybackSegment(ctx_playback, &seg_info->info);
Wentao MA07d3d742022-09-06 09:58:05 +08001050 if (error != DVR_SUCCESS) {
1051 DVR_WRAPPER_ERROR("wrapper_removePlaybackSegment failed with return value %d",error);
1052 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001053 }
hualing chen56c0a162022-01-27 17:01:50 +08001054 ctx_playback->playback.tf_full = DVR_FALSE;
Gong Kefdb31922022-06-17 17:11:16 +08001055 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001056 }
1057 }
1058
Zhiqiang Hanbc3019b2022-03-21 11:31:21 +08001059 uint64_t id = seg_info->info.id;
1060
Wentao MA270dc0f2022-08-23 13:17:26 +08001061 list_for_each_entry_safe_reverse(p_seg, p_seg_tmp, &ctx->segments, head) {
1062 if (p_seg->info.id == id) {
1063 list_del(&p_seg->head);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001064
1065 /*record the obsolete*/
Wentao MA270dc0f2022-08-23 13:17:26 +08001066 ctx->record.obsolete.time += p_seg->info.duration;
1067 ctx->record.obsolete.size += p_seg->info.size;
1068 ctx->record.obsolete.pkts += p_seg->info.nb_packets;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001069
Wentao MA270dc0f2022-08-23 13:17:26 +08001070 free(p_seg);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001071 break;
1072 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001073 }
1074
Zhiqiang Hanbc3019b2022-03-21 11:31:21 +08001075 error = dvr_segment_delete(ctx->record.param_open.location, id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001076
Wentao MAf4072032022-06-30 13:50:45 +08001077 DVR_WRAPPER_INFO("%s, removed record(sn:%ld) segment(%lld), ret=(%d)\n",
1078 __func__, ctx->sn, id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001079
1080 return error;
1081}
1082
1083int dvr_wrapper_open_record (DVR_WrapperRecord_t *rec, DVR_WrapperRecordOpenParams_t *params)
1084{
1085 int error;
1086 DVR_WrapperCtx_t *ctx;
1087 DVR_RecordOpenParams_t open_param;
1088
1089 DVR_RETURN_IF_FALSE(rec);
1090 DVR_RETURN_IF_FALSE(params);
1091
1092 /*get a free ctx*/
1093 ctx = ctx_getRecord(0);
1094 DVR_RETURN_IF_FALSE(ctx);
1095
Gong Kefdb31922022-06-17 17:11:16 +08001096 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001097
Wentao MA9a164002022-08-29 11:20:24 +08001098 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 +08001099 params->dmx_dev_id, params->is_timeshift, params->max_time, params->max_size, params->segment_size);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001100
1101 ctx_reset(ctx);
1102
1103 ctx->record.param_open = *params;
1104 ctx->record.event_fn = params->event_fn;
1105 ctx->record.event_userdata = params->event_userdata;
1106 ctx->record.next_segment_id = 0;
1107 ctx->current_segment_id = 0;
1108 INIT_LIST_HEAD(&ctx->segments);
1109 ctx->sn = get_sn();
1110
1111 wrapper_requestThreadFor(ctx);
1112
hualing chen266b9502020-04-04 17:39:39 +08001113 memset(&open_param, 0, sizeof(DVR_RecordOpenParams_t));
Yahui Hance15e9c2020-12-08 18:08:32 +08001114 open_param.fend_dev_id = params->fend_dev_id;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001115 open_param.dmx_dev_id = params->dmx_dev_id;
1116 open_param.data_from_memory = 0;
1117 open_param.flags = params->flags;
Yahui Han15a00f12021-11-15 19:44:39 +08001118 if (params->flush_size) {
1119 open_param.notification_size = params->flush_size;
1120 } else {
1121 open_param.notification_size = 64*1024;
1122 }
hualing chen002e5b92022-02-23 17:51:21 +08001123 open_param.notification_time = 400;//ms
Zhiqiang Han31505452020-05-06 15:08:10 +08001124 open_param.flush_size = params->flush_size;
hualing chen03fd4942021-07-15 15:56:41 +08001125 open_param.ringbuf_size = params->ringbuf_size;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001126 open_param.event_fn = wrapper_record_event_handler;
1127 open_param.event_userdata = (void*)ctx->sn;
Yahui Han1fbf3292021-11-08 18:17:19 +08001128 if (params->keylen) {
1129 open_param.clearkey = params->clearkey;
1130 open_param.cleariv = params->cleariv;
1131 open_param.keylen = params->keylen;
1132 }
wentao.ma35a69d42022-03-10 18:08:40 +08001133 open_param.force_sysclock = params->force_sysclock;
Wentao MAeeffdb02022-06-27 16:34:35 +08001134 open_param.guarded_segment_size = params->segment_size/2*3;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001135
1136 error = dvr_record_open(&ctx->record.recorder, &open_param);
1137 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001138 DVR_WRAPPER_INFO("record(dmx:%d) open fail(error:%d).\n", params->dmx_dev_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001139 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001140 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001141 wrapper_releaseThreadForType(ctx->type);
1142 return DVR_FAILURE;
1143 }
1144 if (params->is_timeshift)
1145 sn_timeshift_record = ctx->sn;
1146
Wentao MA96f68962022-06-15 19:45:35 +08001147 DVR_WRAPPER_INFO("record(dmx:%d) openned ok(sn:%ld).\n", params->dmx_dev_id, ctx->sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001148
Yahui Han1fbf3292021-11-08 18:17:19 +08001149 if (params->crypto_fn) {
1150 error = dvr_record_set_encrypt_callback(ctx->record.recorder, params->crypto_fn, params->crypto_data);
1151 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001152 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 +08001153 }
hualing chen266b9502020-04-04 17:39:39 +08001154 }
1155
Gong Kefdb31922022-06-17 17:11:16 +08001156 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001157
1158 *rec = (DVR_WrapperRecord_t)ctx->sn;
1159 return DVR_SUCCESS;
1160}
1161
1162int dvr_wrapper_close_record (DVR_WrapperRecord_t rec)
1163{
1164 DVR_WrapperCtx_t *ctx;
1165 DVR_RecordSegmentInfo_t seg_info;
1166 int error;
1167
1168 DVR_RETURN_IF_FALSE(rec);
1169
1170 ctx = ctx_getRecord((unsigned long)rec);
1171 DVR_RETURN_IF_FALSE(ctx);
1172
Gong Kefdb31922022-06-17 17:11:16 +08001173 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001174 DVR_WRAPPER_INFO("close record(sn:%ld)\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001175 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001176
1177 memset(&seg_info, 0, sizeof(seg_info));
wentao.maa210e5e2022-10-12 16:10:03 +08001178 dvr_record_stop_segment(ctx->record.recorder, &seg_info);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001179
1180 error = dvr_record_close(ctx->record.recorder);
1181
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001182 if (ctx->record.param_open.is_timeshift)
1183 sn_timeshift_record = 0;
1184
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001185 ctx_freeSegments(ctx);
1186
Wentao MA96f68962022-06-15 19:45:35 +08001187 DVR_WRAPPER_INFO("record(sn:%ld) closed = (%d).\n", ctx->sn, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001188 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001189 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001190
1191 wrapper_releaseThreadForType(ctx->type);
1192
1193 return error;
1194}
1195
1196int dvr_wrapper_start_record (DVR_WrapperRecord_t rec, DVR_WrapperRecordStartParams_t *params)
1197{
1198 DVR_WrapperCtx_t *ctx;
1199 DVR_RecordStartParams_t *start_param;
1200 int i;
1201 int error;
1202
1203 DVR_RETURN_IF_FALSE(rec);
1204 DVR_RETURN_IF_FALSE(params);
1205
1206 ctx = ctx_getRecord((unsigned long)rec);
1207 DVR_RETURN_IF_FALSE(ctx);
1208
Gong Kefdb31922022-06-17 17:11:16 +08001209 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001210 DVR_WRAPPER_INFO("start record(sn:%ld, location:%s) save(%d)...\n", ctx->sn, ctx->record.param_open.location, params->save_rec_file);
Gong Kefdb31922022-06-17 17:11:16 +08001211 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001212
1213 start_param = &ctx->record.param_start;
1214 memset(start_param, 0, sizeof(*start_param));
Wentao MAe88ad702022-09-02 10:35:00 +08001215 const int len = strlen(ctx->record.param_open.location);
1216 if (len >= DVR_MAX_LOCATION_SIZE || len <= 0) {
1217 DVR_WRAPPER_ERROR("Invalid record.param_open.location length %d",len);
1218 pthread_mutex_unlock(&ctx->wrapper_lock);
1219 return DVR_FAILURE;
1220 }
1221 strncpy(start_param->location, ctx->record.param_open.location, len+1);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001222 start_param->segment.segment_id = ctx->record.next_segment_id++;
1223 start_param->segment.nb_pids = params->pids_info.nb_pids;
1224 for (i = 0; i < params->pids_info.nb_pids; i++) {
1225 start_param->segment.pids[i] = params->pids_info.pids[i];
1226 start_param->segment.pid_action[i] = DVR_RECORD_PID_CREATE;
1227 }
hualing chena5f03222021-12-02 11:22:35 +08001228 if (params->save_rec_file == 0)//default is not save
1229 dvr_segment_del_by_location(start_param->location);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001230 {
1231 /*sync to update for further use*/
1232 DVR_RecordStartParams_t *update_param;
1233 update_param = &ctx->record.param_update;
1234 memcpy(update_param, start_param, sizeof(*update_param));
1235 for (i = 0; i < update_param->segment.nb_pids; i++)
1236 update_param->segment.pid_action[i] = DVR_RECORD_PID_KEEP;
1237 }
1238
1239 error = dvr_record_start_segment(ctx->record.recorder, start_param);
1240 {
1241 DVR_RecordSegmentInfo_t new_seg_info =
1242 { .id = start_param->segment.segment_id, };
1243 wrapper_addRecordSegment(ctx, &new_seg_info);
1244 }
1245
Wentao MA96f68962022-06-15 19:45:35 +08001246 DVR_WRAPPER_INFO("record(sn:%ld) started = (%d)\n", ctx->sn, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001247
Gong Kefdb31922022-06-17 17:11:16 +08001248 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001249
1250 return error;
1251}
1252
1253int dvr_wrapper_stop_record (DVR_WrapperRecord_t rec)
1254{
1255 DVR_WrapperCtx_t *ctx;
1256 DVR_RecordSegmentInfo_t seg_info;
1257 int error;
1258
1259 DVR_RETURN_IF_FALSE(rec);
1260
1261 ctx = ctx_getRecord((unsigned long)rec);
1262 DVR_RETURN_IF_FALSE(ctx);
1263
Gong Kefdb31922022-06-17 17:11:16 +08001264 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001265 DVR_WRAPPER_INFO("stop record(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001266 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001267
1268 memset(&seg_info, 0, sizeof(seg_info));
1269 error = dvr_record_stop_segment(ctx->record.recorder, &seg_info);
1270 wrapper_updateRecordSegment(ctx, &seg_info, U_ALL);
1271
Wentao MA96f68962022-06-15 19:45:35 +08001272 DVR_WRAPPER_INFO("record(sn:%ld) stopped = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001273 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001274
1275 return error;
1276}
1277
hualing chen03fd4942021-07-15 15:56:41 +08001278int dvr_wrapper_pause_record (DVR_WrapperRecord_t rec)
1279{
1280 DVR_WrapperCtx_t *ctx;
1281 int error;
1282
1283 DVR_RETURN_IF_FALSE(rec);
1284
1285 ctx = ctx_getRecord((unsigned long)rec);
1286 DVR_RETURN_IF_FALSE(ctx);
1287
Gong Kefdb31922022-06-17 17:11:16 +08001288 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001289 DVR_WRAPPER_INFO("pause record(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001290 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001291
1292 error = dvr_record_pause(ctx->record.recorder);
1293
Wentao MA96f68962022-06-15 19:45:35 +08001294 DVR_WRAPPER_INFO("record(sn:%ld) pauseed = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001295 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001296
1297 return error;
1298}
1299
1300int dvr_wrapper_resume_record (DVR_WrapperRecord_t rec)
1301{
1302 DVR_WrapperCtx_t *ctx;
1303 int error;
1304
1305 DVR_RETURN_IF_FALSE(rec);
1306
1307 ctx = ctx_getRecord((unsigned long)rec);
1308 DVR_RETURN_IF_FALSE(ctx);
1309
Gong Kefdb31922022-06-17 17:11:16 +08001310 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001311 DVR_WRAPPER_INFO("resume record(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001312 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001313
1314 error = dvr_record_resume(ctx->record.recorder);
1315
Wentao MA96f68962022-06-15 19:45:35 +08001316 DVR_WRAPPER_INFO("record(sn:%ld) resumed = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001317 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001318
1319 return error;
1320}
1321
Wentao MAcdea4762022-04-26 13:28:56 +08001322/* Return true if arr1 contains all elements in arr2 */
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001323static DVR_Bool_t pids_test_include(
1324 DVR_StreamPid_t* arr1, DVR_RecordPidAction_t *act1, int size1,
1325 DVR_StreamPid_t* arr2, DVR_RecordPidAction_t *act2, int size2)
wentao.maa69578c2022-04-07 09:27:39 +08001326{
Wentao MAcdea4762022-04-26 13:28:56 +08001327 DVR_Bool_t ret = DVR_TRUE;
1328 for (int i=0;i<size2;i++)
1329 { // iterate all elements in arr2 to check if they exist in arr1
1330 DVR_Bool_t found=DVR_FALSE;
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001331
1332 if (act2[i] == DVR_RECORD_PID_CLOSE)
1333 continue;
1334
Wentao MAcdea4762022-04-26 13:28:56 +08001335 for (int j=0;j<size1;j++)
wentao.maa69578c2022-04-07 09:27:39 +08001336 {
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001337 if (act1[j] != DVR_RECORD_PID_CLOSE
1338 && arr2[i].pid == arr1[j].pid)
wentao.maa69578c2022-04-07 09:27:39 +08001339 {
1340 found=DVR_TRUE;
1341 break;
1342 }
1343 }
1344 if (found == DVR_FALSE)
1345 {
Wentao MAcdea4762022-04-26 13:28:56 +08001346 ret=DVR_FALSE;
wentao.maa69578c2022-04-07 09:27:39 +08001347 break;
1348 }
1349 }
Wentao MAcdea4762022-04-26 13:28:56 +08001350 return ret;
1351}
1352
1353static DVR_Bool_t pids_equal(const DVR_RecordSegmentStartParams_t* p1,
1354 const DVR_WrapperUpdatePidsParams_t* p2)
1355{
1356 int i=0;
1357 char buf[128]={0};
1358 int cnt=0;
1359 int chars=0;
1360
1361 DVR_RETURN_IF_FALSE(p1 != NULL && p2 != NULL);
1362 DVR_RETURN_IF_FALSE(p1->nb_pids>0 && p2->nb_pids>0);
1363
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001364 DVR_Bool_t cond1 = pids_test_include(p1->pids,p1->pid_action,p1->nb_pids,
1365 p2->pids,p2->pid_action,p2->nb_pids);
1366 DVR_Bool_t cond2 = pids_test_include(p2->pids,p2->pid_action,p2->nb_pids,
1367 p1->pids,p1->pid_action,p1->nb_pids);
Wentao MAcdea4762022-04-26 13:28:56 +08001368 DVR_Bool_t is_equal = (cond1 && cond2);
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001369 int removed;
Wentao MAcdea4762022-04-26 13:28:56 +08001370
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001371 removed = 0;
Wentao MAcdea4762022-04-26 13:28:56 +08001372 for (i=0;i<p1->nb_pids;i++)
1373 {
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001374 if (p1->pid_action[i] == DVR_RECORD_PID_CLOSE) {
1375 removed++;
1376 continue;
1377 }
Wentao MAcdea4762022-04-26 13:28:56 +08001378 chars = snprintf(buf+cnt,sizeof(buf)-cnt,"0x%hx,",p1->pids[i].pid);
1379 if (chars<0)
1380 {
1381 break;
1382 }
1383 cnt += chars;
1384 }
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001385 DVR_INFO("%s nb_pids1:%d, pids1: %s",__func__,p1->nb_pids-removed,buf);
Wentao MAcdea4762022-04-26 13:28:56 +08001386 memset(buf,0,sizeof(buf));
1387
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001388 removed = 0;
Wentao MAcdea4762022-04-26 13:28:56 +08001389 for (i=0,cnt=0;i<p2->nb_pids;i++)
1390 {
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001391 if (p2->pid_action[i] == DVR_RECORD_PID_CLOSE) {
1392 removed++;
1393 continue;
1394 }
Wentao MAcdea4762022-04-26 13:28:56 +08001395 chars = snprintf(buf+cnt,sizeof(buf)-cnt,"0x%hx,",p2->pids[i].pid);
1396 if (chars<0)
1397 {
1398 break;
1399 }
1400 cnt += chars;
1401 }
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001402 DVR_INFO("%s nb_pids2:%d, pids2: %s",__func__,p2->nb_pids-removed,buf);
Wentao MA96f68962022-06-15 19:45:35 +08001403 DVR_INFO("%s is_equal:%d",__func__,is_equal);
wentao.maa69578c2022-04-07 09:27:39 +08001404 return is_equal;
1405}
1406
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001407int dvr_wrapper_update_record_pids (DVR_WrapperRecord_t rec, DVR_WrapperUpdatePidsParams_t *params)
1408{
1409 DVR_WrapperCtx_t *ctx;
1410 DVR_RecordStartParams_t *start_param;
wentao.maa69578c2022-04-07 09:27:39 +08001411 DVR_RecordSegmentInfo_t seg_info;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001412 int i;
1413 int error;
1414
1415 DVR_RETURN_IF_FALSE(rec);
1416 DVR_RETURN_IF_FALSE(params);
1417
1418 ctx = ctx_getRecord((unsigned long)rec);
1419 DVR_RETURN_IF_FALSE(ctx);
1420
Gong Kefdb31922022-06-17 17:11:16 +08001421 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001422 DVR_WRAPPER_INFO("update record(sn:%ld)\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001423 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001424
1425 start_param = &ctx->record.param_update;
wentao.maa69578c2022-04-07 09:27:39 +08001426 if (pids_equal(&(start_param->segment),params))
1427 {
Gong Kefdb31922022-06-17 17:11:16 +08001428 wrapper_mutex_unlock(&ctx->wrapper_lock);
wentao.maa69578c2022-04-07 09:27:39 +08001429 return DVR_TRUE;
1430 }
1431
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001432 memset(start_param, 0, sizeof(*start_param));
Wentao MAe88ad702022-09-02 10:35:00 +08001433 const int len = strlen(ctx->record.param_open.location);
1434 if (len >= DVR_MAX_LOCATION_SIZE || len <= 0) {
1435 DVR_WRAPPER_ERROR("Invalid record.param_open.location length %d",len);
1436 pthread_mutex_unlock(&ctx->wrapper_lock);
1437 return DVR_FAILURE;
1438 }
1439 strncpy(start_param->location, ctx->record.param_open.location, len+1);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001440 start_param->segment.segment_id = ctx->record.next_segment_id++;
1441 start_param->segment.nb_pids = params->nb_pids;
1442 for (i = 0; i < params->nb_pids; i++) {
1443 start_param->segment.pids[i] = params->pids[i];
1444 start_param->segment.pid_action[i] = params->pid_action[i];
1445 }
1446 error = dvr_record_next_segment(ctx->record.recorder, start_param, &seg_info);
1447 {
1448 DVR_RecordSegmentInfo_t new_seg_info =
1449 { .id = start_param->segment.segment_id, };
1450 wrapper_updateRecordSegment(ctx, &seg_info, U_PIDS);
1451 wrapper_addRecordSegment(ctx, &new_seg_info);
1452 }
1453
Wentao MA96f68962022-06-15 19:45:35 +08001454 DVR_WRAPPER_INFO("record(sn:%ld) updated = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001455 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001456
1457 return error;
1458}
1459
1460int dvr_wrapper_get_record_status(DVR_WrapperRecord_t rec, DVR_WrapperRecordStatus_t *status)
1461{
1462 DVR_WrapperCtx_t *ctx;
1463 DVR_WrapperRecordStatus_t s;
1464 int error;
1465
1466 DVR_RETURN_IF_FALSE(rec);
1467 DVR_RETURN_IF_FALSE(status);
1468
1469 ctx = ctx_getRecord((unsigned long)rec);
1470 DVR_RETURN_IF_FALSE(ctx);
1471
Gong Kefdb31922022-06-17 17:11:16 +08001472 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001473
Wentao MA96f68962022-06-15 19:45:35 +08001474 DVR_WRAPPER_INFO("get record(sn:%ld) status ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001475 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001476
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001477 error = process_generateRecordStatus(ctx, &s);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001478
Wentao MA96f68962022-06-15 19:45:35 +08001479 DVR_WRAPPER_INFO("record(sn:%ld) state/time/size/pkts(%d/%ld/%lld/%u) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001480 ctx->sn,
1481 s.state,
1482 s.info.time,
1483 s.info.size,
1484 s.info.pkts,
1485 error);
1486
1487 *status = s;
1488
Gong Kefdb31922022-06-17 17:11:16 +08001489 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001490
1491 return error;
1492}
1493
hualing chen4fe3bee2020-10-23 13:58:52 +08001494int dvr_wrapper_record_is_secure_mode(DVR_WrapperRecord_t rec)
1495{
1496 DVR_WrapperCtx_t *ctx;
1497 int error;
1498
1499 DVR_RETURN_IF_FALSE(rec);
1500
1501 ctx = ctx_getRecord((unsigned long)rec);
1502 DVR_RETURN_IF_FALSE(ctx);
1503
Gong Kefdb31922022-06-17 17:11:16 +08001504 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen4fe3bee2020-10-23 13:58:52 +08001505 error = dvr_record_is_secure_mode(ctx->record.recorder);
Gong Kefdb31922022-06-17 17:11:16 +08001506 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen4fe3bee2020-10-23 13:58:52 +08001507 return error;
1508}
1509
hualing chen266b9502020-04-04 17:39:39 +08001510int dvr_wrapper_set_record_secure_buffer (DVR_WrapperRecord_t rec, uint8_t *p_secure_buf, uint32_t len)
1511{
1512 DVR_WrapperCtx_t *ctx;
1513 int error;
1514
1515 DVR_RETURN_IF_FALSE(rec);
1516 DVR_RETURN_IF_FALSE(p_secure_buf);
1517
1518 ctx = ctx_getRecord((unsigned long)rec);
1519 DVR_RETURN_IF_FALSE(ctx);
1520
Gong Kefdb31922022-06-17 17:11:16 +08001521 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001522 error = dvr_record_set_secure_buffer(ctx->record.recorder, p_secure_buf, len);
Gong Kefdb31922022-06-17 17:11:16 +08001523 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001524 return error;
1525}
1526
1527int dvr_wrapper_set_record_decrypt_callback (DVR_WrapperRecord_t rec, DVR_CryptoFunction_t func, void *userdata)
1528{
1529 DVR_WrapperCtx_t *ctx;
1530 int error;
1531
1532 DVR_RETURN_IF_FALSE(rec);
1533 DVR_RETURN_IF_FALSE(func);
1534
1535 ctx = ctx_getRecord((unsigned long)rec);
1536 DVR_RETURN_IF_FALSE(ctx);
1537
Gong Kefdb31922022-06-17 17:11:16 +08001538 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001539 error = dvr_record_set_encrypt_callback(ctx->record.recorder, func, userdata);
Gong Kefdb31922022-06-17 17:11:16 +08001540 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001541 return error;
1542}
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001543
1544
1545int dvr_wrapper_open_playback (DVR_WrapperPlayback_t *playback, DVR_WrapperPlaybackOpenParams_t *params)
1546{
1547 DVR_WrapperCtx_t *ctx;
1548 DVR_PlaybackOpenParams_t open_param;
1549 int error;
1550
1551 DVR_RETURN_IF_FALSE(playback);
1552 DVR_RETURN_IF_FALSE(params);
1553 DVR_RETURN_IF_FALSE(params->playback_handle);
1554
1555 /*get a free ctx*/
1556 ctx = ctx_getPlayback(0);
1557 DVR_RETURN_IF_FALSE(ctx);
1558
Gong Kefdb31922022-06-17 17:11:16 +08001559 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001560
Wentao MA96f68962022-06-15 19:45:35 +08001561 DVR_WRAPPER_INFO("open playback(dmx:%d) ..vendor[%d]params->block_size[%d].\n", params->dmx_dev_id, params->vendor, params->block_size);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001562
1563 ctx_reset(ctx);
1564
1565 ctx->playback.param_open = *params;
1566 ctx->playback.event_fn = params->event_fn;
1567 ctx->playback.event_userdata = params->event_userdata;
1568 ctx->current_segment_id = 0;
1569 INIT_LIST_HEAD(&ctx->segments);
1570 ctx->sn = get_sn();
1571
1572 wrapper_requestThreadFor(ctx);
1573
hualing chen266b9502020-04-04 17:39:39 +08001574 memset(&open_param, 0, sizeof(DVR_PlaybackOpenParams_t));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001575 open_param.dmx_dev_id = params->dmx_dev_id;
1576 open_param.block_size = params->block_size;
1577 open_param.is_timeshift = params->is_timeshift;
1578 //open_param.notification_size = 10*1024; //not supported
1579 open_param.event_fn = wrapper_playback_event_handler;
1580 open_param.event_userdata = (void*)ctx->sn;
1581 /*open_param.has_pids = 0;*/
hualing chene3797f02021-01-13 14:53:28 +08001582 open_param.is_notify_time = params->is_notify_time;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001583 open_param.player_handle = (am_tsplayer_handle)params->playback_handle;
hualing chen90b3ae62021-03-30 10:49:28 +08001584 open_param.vendor = params->vendor;
1585
Yahui Han1fbf3292021-11-08 18:17:19 +08001586 if (params->keylen) {
1587 open_param.clearkey = params->clearkey;
1588 open_param.cleariv = params->cleariv;
1589 open_param.keylen = params->keylen;
1590 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001591
1592 error = dvr_playback_open(&ctx->playback.player, &open_param);
1593 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001594 DVR_WRAPPER_INFO("playback(dmx:%d) openned fail(error:%d).\n", params->dmx_dev_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001595 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001596 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001597 wrapper_releaseThreadForType(ctx->type);
1598 return DVR_FAILURE;
1599 }
1600 if (params->is_timeshift)
1601 sn_timeshift_playback = ctx->sn;
1602
Wentao MA270dc0f2022-08-23 13:17:26 +08001603 DVR_WRAPPER_INFO("playback(dmx:%d) openned ok(sn:%ld).\n", params->dmx_dev_id, ctx->sn);
hualing chen266b9502020-04-04 17:39:39 +08001604 error = dvr_playback_set_decrypt_callback(ctx->playback.player, params->crypto_fn, params->crypto_data);
1605 if (error) {
Wentao MA270dc0f2022-08-23 13:17:26 +08001606 DVR_WRAPPER_INFO("playback set decrypt callback fail(error:%d).\n", error);
hualing chen266b9502020-04-04 17:39:39 +08001607 }
Gong Kefdb31922022-06-17 17:11:16 +08001608 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001609
1610 *playback = (DVR_WrapperPlayback_t)ctx->sn;
1611 return DVR_SUCCESS;
1612}
1613
1614int dvr_wrapper_close_playback (DVR_WrapperPlayback_t playback)
1615{
1616 DVR_WrapperCtx_t *ctx;
1617 int error;
1618
1619 DVR_RETURN_IF_FALSE(playback);
1620
1621 ctx = ctx_getPlayback((unsigned long)playback);
1622 DVR_RETURN_IF_FALSE(ctx);
1623
Gong Kefdb31922022-06-17 17:11:16 +08001624 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001625 DVR_WRAPPER_INFO("close playback(sn:%ld)\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001626 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001627
1628 if (ctx->playback.param_open.is_timeshift)
1629 sn_timeshift_playback = 0;
1630
1631 /*try stop first*/
wentao.maa210e5e2022-10-12 16:10:03 +08001632 dvr_playback_stop(ctx->playback.player, DVR_TRUE);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001633
1634 {
1635 /*remove all segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08001636 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001637
wentao.maa22bc852022-10-13 12:18:06 +08001638 // This error is surpressed as the macro code is picked from kernel.
1639 // prefetch() here incurring self_assign is used to avoid some compiling
1640 // warnings.
1641 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08001642 list_for_each_entry(p_seg, &ctx->segments, head) {
1643 error = dvr_playback_remove_segment(ctx->playback.player, p_seg->playback_info.segment_id);
Wentao MA96f68962022-06-15 19:45:35 +08001644 DVR_WRAPPER_INFO("playback(sn:%ld) remove seg(%lld) (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08001645 ctx->sn, p_seg->playback_info.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001646 }
1647 ctx_freeSegments(ctx);
1648 }
1649
1650 error = dvr_playback_close(ctx->playback.player);
1651
Wentao MA96f68962022-06-15 19:45:35 +08001652 DVR_WRAPPER_INFO("playback(sn:%ld) closed.\n", ctx->sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001653 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001654 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001655
1656 wrapper_releaseThreadForType(ctx->type);
1657
1658 return error;
1659}
1660
1661int dvr_wrapper_start_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackFlag_t flags, DVR_PlaybackPids_t *p_pids)
1662{
1663 DVR_WrapperCtx_t *ctx;
Wentao MA9aa0aa02021-12-23 18:30:17 +08001664 int error=0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001665 uint64_t *p_segment_ids;
1666 uint32_t segment_nb;
1667 uint32_t i;
1668 DVR_RecordSegmentInfo_t seg_info_1st;
Wentao MA9aa0aa02021-12-23 18:30:17 +08001669 int got_1st_seg=0;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001670 DVR_WrapperCtx_t *ctx_record;/*for timeshift*/
hualing chenc110f952021-01-18 11:25:37 +08001671 DVR_Bool_t is_timeshift = DVR_FALSE;
wentao.maf57dd232022-10-08 16:07:29 +08001672 DVR_PlaybackSegmentFlag_t segflags = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001673
1674 DVR_RETURN_IF_FALSE(playback);
1675 DVR_RETURN_IF_FALSE(p_pids);
1676
hualing chenc110f952021-01-18 11:25:37 +08001677 ctx_record = NULL;
1678
1679 /*lock the recorder to avoid changing the recording segments*/
1680 ctx_record = ctx_getRecord(sn_timeshift_record);
1681
1682 if (ctx_record) {
Gong Kefdb31922022-06-17 17:11:16 +08001683 wrapper_mutex_lock(&ctx_record->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001684 if (!ctx_valid(ctx_record)
1685 || ctx_record->sn != sn_timeshift_record) {
Wentao MA96f68962022-06-15 19:45:35 +08001686 DVR_WRAPPER_INFO("timeshift, record is not for timeshifting, FATAL error found\n");
Gong Kefdb31922022-06-17 17:11:16 +08001687 wrapper_mutex_unlock(&ctx_record->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001688 is_timeshift = DVR_FALSE;
1689 } else {
1690 is_timeshift = DVR_TRUE;
1691 }
1692 }
1693
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001694 ctx = ctx_getPlayback((unsigned long)playback);
1695 DVR_RETURN_IF_FALSE(ctx);
1696
Gong Kefdb31922022-06-17 17:11:16 +08001697 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001698
Wentao MA96f68962022-06-15 19:45:35 +08001699 DVR_WRAPPER_INFO("start playback(sn:%ld) (%s)\n\t flags(0x%x) v/a/ad/sub/pcr(%d:%d %d:%d %d:%d %d:%d %d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001700 ctx->sn,
1701 ctx->playback.param_open.location,
1702 flags,
1703 p_pids->video.pid, p_pids->video.format,
1704 p_pids->audio.pid, p_pids->audio.format,
1705 p_pids->ad.pid, p_pids->ad.format,
1706 p_pids->subtitle.pid, p_pids->subtitle.format,
1707 p_pids->pcr.pid);
1708
Gong Kefdb31922022-06-17 17:11:16 +08001709 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001710
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001711 if (ctx->playback.param_open.is_timeshift) {
1712 /*lock the recorder to avoid changing the recording segments*/
hualing chenc110f952021-01-18 11:25:37 +08001713 if (is_timeshift == DVR_FALSE) {
Wentao MA96f68962022-06-15 19:45:35 +08001714 DVR_WRAPPER_INFO("timeshift, record is not for timeshifting, FATAL error return\n");
Gong Kefdb31922022-06-17 17:11:16 +08001715 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001716 return DVR_FAILURE;
1717 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001718 DVR_WRAPPER_INFO("playback(sn:%ld) record(sn:%ld) locked ok due to timeshift\n",
hualing chenc110f952021-01-18 11:25:37 +08001719 ctx->sn, ctx_record->sn);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001720 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001721 }
1722
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001723 /*obtain all segments in a list*/
1724 segment_nb = 0;
1725 p_segment_ids = NULL;
1726 error = dvr_segment_get_list(ctx->playback.param_open.location, &segment_nb, &p_segment_ids);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001727 if (!error) {
1728 got_1st_seg = 0;
hualing chenb9a02922021-12-14 11:29:47 +08001729 struct list_head info_list; /**< segment list head*/
1730 INIT_LIST_HEAD(&info_list);
1731
Wentao MA96f68962022-06-15 19:45:35 +08001732 DVR_WRAPPER_INFO("get list segment_nb::%d",segment_nb);
hualing chenb9a02922021-12-14 11:29:47 +08001733 //we need free info list buf when we used end.
1734 error = dvr_segment_get_allInfo(ctx->playback.param_open.location, &info_list);
hualing chen926a8ec2021-12-20 20:38:24 +08001735 if (error == DVR_FAILURE) {
hualing chenb9a02922021-12-14 11:29:47 +08001736 error = DVR_FAILURE;
Zhiqiang Handc3bfe52022-07-07 10:48:39 +08001737 DVR_WRAPPER_INFO("fail to get all seg info (location:%s), (error:%d)\n",
1738 ctx->playback.param_open.location, error);
wentao.maf57dd232022-10-08 16:07:29 +08001739 // Tainted data issue originating from fgets seem false positive, so we
1740 // just suppress it here.
1741 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08001742 for (i = 0; i < segment_nb; i++) {
1743 DVR_RecordSegmentInfo_t seg_info;
Wentao MA4d85ff32022-09-23 11:36:18 +08001744 memset((void*)&seg_info,0,sizeof(seg_info));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001745
hualing chenb9a02922021-12-14 11:29:47 +08001746 error = dvr_segment_get_info(ctx->playback.param_open.location, p_segment_ids[i], &seg_info);
1747 if (error) {
1748 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08001749 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chenb9a02922021-12-14 11:29:47 +08001750 ctx->playback.param_open.location, p_segment_ids[i], error);
1751 break;
1752 }
1753 //add check if has audio or video pid. if not exist. not add segment to playback
1754 int ii = 0;
1755 int has_av = 0;
wentao.maf57dd232022-10-08 16:07:29 +08001756 // Tainted data issue originating from fgets seem false positive, so we
1757 // just suppress it here.
1758 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08001759 for (ii = 0; ii < seg_info.nb_pids; ii++) {
1760 int type = (seg_info.pids[ii].type >> 24) & 0x0f;
1761 if (type == DVR_STREAM_TYPE_VIDEO ||
1762 type == DVR_STREAM_TYPE_AUDIO ||
1763 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001764 DVR_WRAPPER_INFO("success to get seg av info \n");
1765 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 +08001766 DVR_STREAM_TYPE_VIDEO,
1767 DVR_STREAM_TYPE_AUDIO,
1768 DVR_STREAM_TYPE_AD);
1769 has_av = 1;
1770 //break;
1771 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001772 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 +08001773 DVR_STREAM_TYPE_VIDEO,
1774 DVR_STREAM_TYPE_AUDIO,
1775 DVR_STREAM_TYPE_AD);
1776 }
1777 }
1778 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001779 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001780 continue;
1781 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001782 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001783 }
Wentao MA9628de82022-09-13 14:19:37 +08001784 segflags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
1785 error = wrapper_addPlaybackSegment(ctx, &seg_info, p_pids, segflags);
wentao.maa210e5e2022-10-12 16:10:03 +08001786 if (error == DVR_FAILURE) {
1787 DVR_WRAPPER_WARN("adding playback segment fails");
hualing chenb9a02922021-12-14 11:29:47 +08001788 break;
wentao.maa210e5e2022-10-12 16:10:03 +08001789 }
hualing chenb9a02922021-12-14 11:29:47 +08001790 /*copy the 1st segment*/
1791 if (got_1st_seg == 0) {
1792 seg_info_1st = seg_info;
1793 got_1st_seg = 1;
1794 }
1795 }
1796 } else {
wentao.maf57dd232022-10-08 16:07:29 +08001797 // Tainted data issue originating from fgets seem false positive, so we
1798 // just suppress it here.
1799 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08001800 for (i = 0; i < segment_nb; i++) {
Wentao MA4d85ff32022-09-23 11:36:18 +08001801 DVR_RecordSegmentInfo_t *p_seg_info;
hualing chenb9a02922021-12-14 11:29:47 +08001802 int found = 0;
wentao.maa22bc852022-10-13 12:18:06 +08001803 // This error is surpressed as the macro code is picked from kernel.
1804 // prefetch() here incurring self_assign is used to avoid some compiling
1805 // warnings.
1806 // coverity[self_assign]
Wentao MA4d85ff32022-09-23 11:36:18 +08001807 list_for_each_entry(p_seg_info, &info_list, head)
hualing chenb9a02922021-12-14 11:29:47 +08001808 {
Wentao MA4d85ff32022-09-23 11:36:18 +08001809 if (p_seg_info->id == p_segment_ids[i]) {
hualing chenb9a02922021-12-14 11:29:47 +08001810 found = 1;
Wentao MA96f68962022-06-15 19:45:35 +08001811 DVR_WRAPPER_INFO("get segment info::%d", i);
hualing chenb9a02922021-12-14 11:29:47 +08001812 break;
1813 }
1814 }
1815 if (!found) {
hualing chen8aed9582021-12-24 17:59:56 +08001816 //last info is not found if when recording occured power off.
1817 if (p_segment_ids[i] == segment_nb - 1) {
1818 DVR_RecordSegmentInfo_t seg_info;
Wentao MA4d85ff32022-09-23 11:36:18 +08001819 memset((void*)&seg_info,0,sizeof(seg_info));
hualing chen8aed9582021-12-24 17:59:56 +08001820
1821 error = dvr_segment_get_info(ctx->playback.param_open.location, p_segment_ids[i], &seg_info);
1822 if (error) {
1823 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08001824 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chen8aed9582021-12-24 17:59:56 +08001825 ctx->playback.param_open.location, p_segment_ids[i], error);
1826 break;
1827 }
1828 //
1829 //add check if has audio or video pid. if not exist. not add segment to playback
1830 int ii = 0;
1831 int has_av = 0;
wentao.maf57dd232022-10-08 16:07:29 +08001832 // Tainted data issue originating from fgets seem false positive, so we
1833 // just suppress it here.
1834 // coverity[tainted_data]
hualing chen8aed9582021-12-24 17:59:56 +08001835 for (ii = 0; ii < seg_info.nb_pids; ii++) {
1836 int type = (seg_info.pids[ii].type >> 24) & 0x0f;
1837 if (type == DVR_STREAM_TYPE_VIDEO ||
1838 type == DVR_STREAM_TYPE_AUDIO ||
1839 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001840 DVR_WRAPPER_INFO("success to get seg av info \n");
1841 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 +08001842 DVR_STREAM_TYPE_VIDEO,
1843 DVR_STREAM_TYPE_AUDIO,
1844 DVR_STREAM_TYPE_AD);
1845 has_av = 1;
1846 //break;
1847 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001848 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 +08001849 DVR_STREAM_TYPE_VIDEO,
1850 DVR_STREAM_TYPE_AUDIO,
1851 DVR_STREAM_TYPE_AD);
1852 }
1853 }
1854 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001855 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chen8aed9582021-12-24 17:59:56 +08001856 continue;
1857 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001858 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chen8aed9582021-12-24 17:59:56 +08001859 }
Wentao MA9628de82022-09-13 14:19:37 +08001860 segflags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
1861 error = wrapper_addPlaybackSegment(ctx, &seg_info, p_pids, segflags);
wentao.maa210e5e2022-10-12 16:10:03 +08001862 if (error == DVR_FAILURE) {
1863 DVR_WRAPPER_WARN("adding playback segment fails");
hualing chen8aed9582021-12-24 17:59:56 +08001864 break;
wentao.maa210e5e2022-10-12 16:10:03 +08001865 }
hualing chen8aed9582021-12-24 17:59:56 +08001866 }
hualing chenb9a02922021-12-14 11:29:47 +08001867 continue;
1868 }
1869
1870 //add check if has audio or video pid. if not exist. not add segment to playback
1871 int ii = 0;
1872 int has_av = 0;
Wentao MA4d85ff32022-09-23 11:36:18 +08001873 for (ii = 0; ii < p_seg_info->nb_pids; ii++) {
1874 int type = (p_seg_info->pids[ii].type >> 24) & 0x0f;
hualing chenb9a02922021-12-14 11:29:47 +08001875 if (type == DVR_STREAM_TYPE_VIDEO ||
1876 type == DVR_STREAM_TYPE_AUDIO ||
1877 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001878 DVR_WRAPPER_INFO("success to get seg av info \n");
Wentao MA4d85ff32022-09-23 11:36:18 +08001879 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 +08001880 DVR_STREAM_TYPE_VIDEO,
1881 DVR_STREAM_TYPE_AUDIO,
1882 DVR_STREAM_TYPE_AD);
1883 has_av = 1;
1884 //break;
1885 } else {
Wentao MA4d85ff32022-09-23 11:36:18 +08001886 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 +08001887 DVR_STREAM_TYPE_VIDEO,
1888 DVR_STREAM_TYPE_AUDIO,
1889 DVR_STREAM_TYPE_AD);
1890 }
1891 }
1892 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001893 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001894 continue;
1895 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001896 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001897 }
Wentao MA9628de82022-09-13 14:19:37 +08001898 segflags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
Wentao MA4d85ff32022-09-23 11:36:18 +08001899 error = wrapper_addPlaybackSegment(ctx, p_seg_info, p_pids, segflags);
wentao.maa210e5e2022-10-12 16:10:03 +08001900 if (error == DVR_FAILURE) {
1901 DVR_WRAPPER_WARN("adding playback segment fails");
hualing chenb9a02922021-12-14 11:29:47 +08001902 break;
wentao.maa210e5e2022-10-12 16:10:03 +08001903 }
hualing chenb9a02922021-12-14 11:29:47 +08001904
1905 /*copy the 1st segment*/
1906 if (got_1st_seg == 0) {
Wentao MA4d85ff32022-09-23 11:36:18 +08001907 seg_info_1st = *p_seg_info;
hualing chenb9a02922021-12-14 11:29:47 +08001908 got_1st_seg = 1;
1909 }
hualing chen92f3a142020-07-08 20:59:33 +08001910 }
hualing chenb9a02922021-12-14 11:29:47 +08001911 //free list
1912 DVR_RecordSegmentInfo_t *segment = NULL;
1913 DVR_RecordSegmentInfo_t *segment_tmp = NULL;
1914 list_for_each_entry_safe(segment, segment_tmp, &info_list, head)
1915 {
1916 if (segment) {
1917 list_del(&segment->head);
1918 free(segment);
1919 }
1920 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001921 }
hualing chenb9a02922021-12-14 11:29:47 +08001922
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001923 free(p_segment_ids);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001924
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001925 /* return if no segment or fail to add */
1926 if (!error && got_1st_seg) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001927
Wentao MA270dc0f2022-08-23 13:17:26 +08001928 /*copy the obsolete information, must for timeshifting*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001929 if (ctx->playback.param_open.is_timeshift && ctx_record) {
1930 ctx->playback.obsolete = ctx_record->record.obsolete;
1931 }
1932
Wentao MA96f68962022-06-15 19:45:35 +08001933 DVR_WRAPPER_INFO("playback(sn:%ld) (%d) segments added\n", ctx->sn, i);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001934
1935 ctx->playback.reach_end = DVR_FALSE;
1936 if ((flags&DVR_PLAYBACK_STARTED_PAUSEDLIVE) == DVR_PLAYBACK_STARTED_PAUSEDLIVE)
1937 ctx->playback.speed = 0.0f;
1938 else
1939 ctx->playback.speed = 100.0f;
1940
1941 ctx->playback.pids_req = *p_pids;
Wentao MA270dc0f2022-08-23 13:17:26 +08001942 //calculate segment id and pos
hualing chen03fd4942021-07-15 15:56:41 +08001943 if (dvr_playback_check_limit(ctx->playback.player)) {
Gong Kefdb31922022-06-17 17:11:16 +08001944 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001945 dvr_wrapper_seek_playback(playback, 0);
Gong Kefdb31922022-06-17 17:11:16 +08001946 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001947 error = dvr_playback_start(ctx->playback.player, flags);
1948 } else {
wentao.maa210e5e2022-10-12 16:10:03 +08001949 dvr_playback_seek(ctx->playback.player, seg_info_1st.id, 0);
hualing chen03fd4942021-07-15 15:56:41 +08001950 error = dvr_playback_start(ctx->playback.player, flags);
Wentao MA96f68962022-06-15 19:45:35 +08001951 DVR_WRAPPER_INFO("playback(sn:%ld) seek(seg:%llu 0) for start (%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08001952 ctx->sn, seg_info_1st.id, error);
1953 }
Wentao MA96f68962022-06-15 19:45:35 +08001954 DVR_WRAPPER_INFO("playback(sn:%ld) started (%d)\n", ctx->sn, error);
hualing chen451c8f72022-03-09 13:05:52 +08001955 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001956 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 +08001957 }
1958 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001959
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001960 if (ctx->playback.param_open.is_timeshift) {
1961 /*unlock the recorder locked above*/
1962 if (ctx_record && ctx_valid(ctx_record)) {
Gong Kefdb31922022-06-17 17:11:16 +08001963 wrapper_mutex_unlock(&ctx_record->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001964 DVR_WRAPPER_INFO("playback(sn:%ld), record(sn:%ld) unlocked ok due to timeshift\n",
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001965 ctx->sn, ctx_record->sn);
1966 }
1967 }
Gong Kefdb31922022-06-17 17:11:16 +08001968 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001969
1970 return error;
1971}
hualing chen002e5b92022-02-23 17:51:21 +08001972//stop record and playback
1973int dvr_wrapper_stop_timeshift (DVR_WrapperPlayback_t playback)
1974{
1975 DVR_WrapperCtx_t *ctx_record = NULL;/*for timeshift*/
1976 int error;
Wentao MA96f68962022-06-15 19:45:35 +08001977 DVR_WRAPPER_INFO("stop timeshift record\n");
hualing chen002e5b92022-02-23 17:51:21 +08001978
1979 //stop timeshift record
1980 ctx_record = ctx_getRecord(sn_timeshift_record);
wentao.maa210e5e2022-10-12 16:10:03 +08001981 dvr_wrapper_stop_record((DVR_WrapperRecord_t)sn_timeshift_record);
hualing chen002e5b92022-02-23 17:51:21 +08001982
Wentao MA96f68962022-06-15 19:45:35 +08001983 DVR_WRAPPER_INFO("stop timeshift ...stop play\n");
hualing chen002e5b92022-02-23 17:51:21 +08001984 //stop play
1985 error = dvr_wrapper_stop_playback(playback);
1986 //del timeshift file
1987 if (ctx_record != NULL) {
Wentao MA96f68962022-06-15 19:45:35 +08001988 DVR_WRAPPER_INFO("del timeshift(sn:%ld) ...3\n", ctx_record->sn);
hualing chen002e5b92022-02-23 17:51:21 +08001989 error = dvr_segment_del_by_location(ctx_record->record.param_open.location);
1990 }
1991 return error;
1992}
1993//start record and start playback
1994int dvr_wrapper_restart_timeshift(DVR_WrapperPlayback_t playback, DVR_PlaybackFlag_t flags, DVR_PlaybackPids_t *p_pids)
1995{
1996 DVR_WrapperCtx_t *ctx;
1997 DVR_RecordStartParams_t *start_param;
1998 int error;
1999
2000 ctx = ctx_getRecord((unsigned long)sn_timeshift_record);
2001 DVR_RETURN_IF_FALSE(ctx);
2002
Gong Kefdb31922022-06-17 17:11:16 +08002003 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08002004 DVR_WRAPPER_INFO("restart record(sn:%ld, location:%s)...\n", ctx->sn, ctx->record.param_open.location);
Gong Kefdb31922022-06-17 17:11:16 +08002005 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen002e5b92022-02-23 17:51:21 +08002006
hualing chen451c8f72022-03-09 13:05:52 +08002007 {
2008 //clear old record status
2009 // struct {
2010 // DVR_WrapperRecordOpenParams_t param_open;
2011 // DVR_RecordStartParams_t param_start;
2012 // DVR_RecordStartParams_t param_update;
2013 // DVR_RecordHandle_t recorder;
2014 // DVR_RecordEventFunction_t event_fn;
2015 // void *event_userdata;
2016
2017 // /*total status = seg_status + status + obsolete*/
2018 // DVR_RecordStatus_t seg_status; /**<status of current segment*/
2019 // DVR_WrapperRecordStatus_t status; /**<status of remaining segments*/
2020 // uint64_t next_segment_id;
2021
2022 // DVR_WrapperInfo_t obsolete; /**<data obsolete due to the max limit*/
2023 // } record;
2024 memset(&(ctx->record.seg_status), 0, sizeof(DVR_RecordStatus_t));
2025 memset(&(ctx->record.status), 0, sizeof(DVR_WrapperRecordStatus_t));
2026 memset(&(ctx->record.obsolete), 0, sizeof(DVR_WrapperInfo_t));
2027 }
2028
hualing chen002e5b92022-02-23 17:51:21 +08002029 start_param = &ctx->record.param_start;
2030
2031 error = dvr_record_start_segment(ctx->record.recorder, start_param);
2032 {
2033 DVR_RecordSegmentInfo_t new_seg_info =
2034 { .id = start_param->segment.segment_id, };
2035 wrapper_addRecordSegment(ctx, &new_seg_info);
Wentao MA96f68962022-06-15 19:45:35 +08002036 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 +08002037 ctx->record.next_segment_id = start_param->segment.segment_id + 1;
2038 DVR_RecordStartParams_t *update_param;
2039 update_param = &ctx->record.param_update;
2040 memcpy(update_param, start_param, sizeof(*update_param));
2041 int i = 0;
2042 for (i = 0; i < update_param->segment.nb_pids; i++)
2043 update_param->segment.pid_action[i] = DVR_RECORD_PID_KEEP;
hualing chen002e5b92022-02-23 17:51:21 +08002044 }
2045
Wentao MA96f68962022-06-15 19:45:35 +08002046 DVR_WRAPPER_INFO("re record(sn:%ld) started = (%d)\n", ctx->sn, error);
hualing chen002e5b92022-02-23 17:51:21 +08002047
Gong Kefdb31922022-06-17 17:11:16 +08002048 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen002e5b92022-02-23 17:51:21 +08002049
2050 //start play
Wentao MA96f68962022-06-15 19:45:35 +08002051 DVR_WRAPPER_INFO("re start play and clear old status\n");
hualing chen451c8f72022-03-09 13:05:52 +08002052 //clear play statue
2053 ctx = ctx_getPlayback((unsigned long)playback);
2054 if (ctx) {
Wentao MA4d85ff32022-09-23 11:36:18 +08002055 //reset old playback status
hualing chen451c8f72022-03-09 13:05:52 +08002056 // struct {
2057 // DVR_WrapperPlaybackOpenParams_t param_open;
2058 // DVR_PlaybackHandle_t player;
2059 // DVR_PlaybackEventFunction_t event_fn;
2060 // void *event_userdata;
2061
2062 // /*total status = seg_status + status*/
2063 // DVR_PlaybackStatus_t seg_status;
2064 // DVR_WrapperPlaybackStatus_t status;
2065 // DVR_PlaybackPids_t pids_req;
2066 // DVR_PlaybackEvent_t last_event;
2067 // float speed;
2068 // DVR_Bool_t reach_end;
2069
2070 // DVR_WrapperInfo_t obsolete;
2071 // DVR_Bool_t tf_full;
2072 // } playback;
Wentao MA4d85ff32022-09-23 11:36:18 +08002073 ctx->playback.tf_full = DVR_FALSE;
2074 ctx->playback.reach_end = DVR_FALSE;
hualing chen451c8f72022-03-09 13:05:52 +08002075 memset(&(ctx->playback.last_event), 0, sizeof(DVR_PlaybackEvent_t));
2076 memset(&(ctx->playback.seg_status), 0, sizeof(DVR_PlaybackStatus_t));
2077 memset(&(ctx->playback.status), 0, sizeof(DVR_WrapperPlaybackStatus_t));
2078 memset(&(ctx->playback.obsolete), 0, sizeof(DVR_WrapperInfo_t));
2079 }
hualing chen002e5b92022-02-23 17:51:21 +08002080 error = dvr_wrapper_start_playback(playback, flags, p_pids);
2081 return error;
2082}
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002083
2084int dvr_wrapper_stop_playback (DVR_WrapperPlayback_t playback)
2085{
2086 DVR_WrapperCtx_t *ctx;
2087 int error;
2088
2089 DVR_RETURN_IF_FALSE(playback);
2090
2091 ctx = ctx_getPlayback((unsigned long)playback);
2092 DVR_RETURN_IF_FALSE(ctx);
2093
Gong Kefdb31922022-06-17 17:11:16 +08002094 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08002095 DVR_WRAPPER_INFO("stop playback(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002096 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002097
2098 error = dvr_playback_stop(ctx->playback.player, DVR_TRUE);
2099
2100 {
2101 /*remove all segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002102 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002103
wentao.maa22bc852022-10-13 12:18:06 +08002104 // This error is surpressed as the macro code is picked from kernel.
2105 // prefetch() here incurring self_assign is used to avoid some compiling
2106 // warnings.
2107 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002108 list_for_each_entry(p_seg, &ctx->segments, head) {
2109 error = dvr_playback_remove_segment(ctx->playback.player, p_seg->playback_info.segment_id);
Wentao MA96f68962022-06-15 19:45:35 +08002110 DVR_WRAPPER_INFO("playback(sn:%ld) remove seg(%lld) (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08002111 ctx->sn, p_seg->playback_info.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002112 }
2113 ctx_freeSegments(ctx);
2114 }
2115
Wentao MA96f68962022-06-15 19:45:35 +08002116 DVR_WRAPPER_INFO("playback(sn:%ld) stopped (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002117 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002118
2119 return error;
2120}
2121
2122int dvr_wrapper_pause_playback (DVR_WrapperPlayback_t playback)
2123{
2124 DVR_WrapperCtx_t *ctx;
2125 int error;
2126
2127 DVR_RETURN_IF_FALSE(playback);
2128
2129 ctx = ctx_getPlayback((unsigned long)playback);
2130 DVR_RETURN_IF_FALSE(ctx);
2131
Gong Kefdb31922022-06-17 17:11:16 +08002132 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08002133 DVR_WRAPPER_INFO("pause playback(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002134 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen36e0dfd2020-05-02 16:33:06 +08002135 //clear end event
Zhiqiang Hanb723cdb2020-05-09 11:10:29 +08002136 if (ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_END)
hualing chen36e0dfd2020-05-02 16:33:06 +08002137 ctx->playback.last_event = DVR_PLAYBACK_EVENT_TRANSITION_OK;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002138
2139 error = dvr_playback_pause(ctx->playback.player, DVR_FALSE);
2140
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002141 ctx->playback.speed = 0.0f;
2142
Wentao MA96f68962022-06-15 19:45:35 +08002143 DVR_WRAPPER_INFO("playback(sn:%ld) paused (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002144 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002145
2146 return error;
2147}
2148
2149int dvr_wrapper_resume_playback (DVR_WrapperPlayback_t playback)
2150{
2151 DVR_WrapperCtx_t *ctx;
2152 int error;
2153
2154 DVR_RETURN_IF_FALSE(playback);
2155
2156 ctx = ctx_getPlayback((unsigned long)playback);
2157 DVR_RETURN_IF_FALSE(ctx);
hualing chen03fd4942021-07-15 15:56:41 +08002158 //if set limit.we need check if seek to valid data when resume
2159 uint32_t time_offset = ctx->playback.status.info_cur.time + ctx->playback.status.info_obsolete.time;
2160 if (dvr_playback_check_limit(ctx->playback.player)) {
2161 int expired = dvr_playback_calculate_expiredlen(ctx->playback.player);
2162 if (expired > time_offset) {
Wentao MA96f68962022-06-15 19:45:35 +08002163 DVR_WRAPPER_INFO("seek before resume reset offset playback(sn:%ld) (off:%d expired:%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08002164 ctx->sn, time_offset, expired);
2165 time_offset = expired;
2166 dvr_wrapper_seek_playback(playback, time_offset);
2167 }
2168 }
Gong Kefdb31922022-06-17 17:11:16 +08002169 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08002170 DVR_WRAPPER_INFO("resume playback(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002171 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002172
2173 error = dvr_playback_resume(ctx->playback.player);
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002174 ctx->playback.speed = 100.0f;
2175
Wentao MA96f68962022-06-15 19:45:35 +08002176 DVR_WRAPPER_INFO("playback(sn:%ld) resumed (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002177 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002178
2179 return error;
2180}
2181
2182int dvr_wrapper_set_playback_speed (DVR_WrapperPlayback_t playback, float speed)
2183{
2184 DVR_WrapperCtx_t *ctx;
2185 int error;
2186 DVR_PlaybackSpeed_t dvr_speed = {
2187 .speed = { speed },
2188 .mode = (speed > 0) ? DVR_PLAYBACK_FAST_FORWARD : DVR_PLAYBACK_FAST_BACKWARD
2189 };
2190
2191 DVR_RETURN_IF_FALSE(playback);
2192
2193 ctx = ctx_getPlayback((unsigned long)playback);
2194 DVR_RETURN_IF_FALSE(ctx);
2195
Gong Kefdb31922022-06-17 17:11:16 +08002196 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08002197 DVR_WRAPPER_INFO("speed playback(sn:%ld) (x%f) .(x%f)..\n", ctx->sn, speed, ctx->playback.speed);
Gong Kefdb31922022-06-17 17:11:16 +08002198 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002199
2200 error = dvr_playback_set_speed(ctx->playback.player, dvr_speed);
2201
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002202 if (ctx->playback.speed != 0.0f && ctx->playback.speed != 100.0f
2203 && ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_BEGIN
2204 && ctx->playback.seg_status.state == DVR_PLAYBACK_STATE_PAUSE) {
Wentao MA96f68962022-06-15 19:45:35 +08002205 DVR_WRAPPER_INFO("x%f -> x%f, paused, do resume first\n", ctx->playback.speed, speed);
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002206 error = dvr_playback_resume(ctx->playback.player);
2207 } else if (ctx->playback.speed == 0.0f
2208 && speed != 0.0f
2209 && speed != 100.0f) {
2210 /*libdvr do not support pause with speed=0, will not be here*/
Wentao MA96f68962022-06-15 19:45:35 +08002211 DVR_WRAPPER_INFO("x%f -> x%f, do resume first\n", ctx->playback.speed, speed);
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002212 error = dvr_playback_resume(ctx->playback.player);
2213 }
2214
2215 ctx->playback.speed = speed;
2216
Wentao MA96f68962022-06-15 19:45:35 +08002217 DVR_WRAPPER_INFO("playback(sn:%ld) speeded(x%f) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002218 ctx->sn, speed, error);
Gong Kefdb31922022-06-17 17:11:16 +08002219 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002220
2221 return error;
2222}
2223
hualing chen03fd4942021-07-15 15:56:41 +08002224int dvr_wrapper_setlimit_playback (DVR_WrapperPlayback_t playback, uint64_t time, int32_t limit)
2225{
2226 DVR_WrapperCtx_t *ctx;
2227 int error;
2228
2229 DVR_RETURN_IF_FALSE(playback);
2230
2231 ctx = ctx_getPlayback((unsigned long)playback);
2232 DVR_RETURN_IF_FALSE(ctx);
2233
Gong Kefdb31922022-06-17 17:11:16 +08002234 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002235
Wentao MAe8ba5172022-08-09 11:18:17 +08002236 DVR_WRAPPER_INFO("set_limit playback(sn:%ld) (time:%lld limit:%d) ...\n", ctx->sn, time, limit);
Gong Kefdb31922022-06-17 17:11:16 +08002237 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002238
2239 error = dvr_playback_setlimit(ctx->playback.player, time, limit);
Wentao MAe8ba5172022-08-09 11:18:17 +08002240 DVR_WRAPPER_INFO("playback(sn:%ld) set_limit(time:%lld limit:%d) ...\n", ctx->sn, time, limit);
hualing chen03fd4942021-07-15 15:56:41 +08002241
Gong Kefdb31922022-06-17 17:11:16 +08002242 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002243
2244 return error;
2245}
2246
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002247int dvr_wrapper_seek_playback (DVR_WrapperPlayback_t playback, uint32_t time_offset)
2248{
2249 DVR_WrapperCtx_t *ctx;
2250 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08002251 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002252 uint64_t segment_id;
2253 uint32_t off;
2254 uint64_t last_segment_id;
2255 uint32_t pre_off;
2256
2257 DVR_RETURN_IF_FALSE(playback);
2258
2259 ctx = ctx_getPlayback((unsigned long)playback);
2260 DVR_RETURN_IF_FALSE(ctx);
2261
Gong Kefdb31922022-06-17 17:11:16 +08002262 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002263
Wentao MA96f68962022-06-15 19:45:35 +08002264 DVR_WRAPPER_INFO("seek playback(sn:%ld) (off:%d) ...\n", ctx->sn, time_offset);
Gong Kefdb31922022-06-17 17:11:16 +08002265 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002266
2267 off = 0;
2268 segment_id = 0;
2269 pre_off = 0;
2270 last_segment_id = 0;
2271
hualing chen03fd4942021-07-15 15:56:41 +08002272 //if set limit info we need check ts data is
2273 //expired when seek
2274 if (dvr_playback_check_limit(ctx->playback.player)) {
2275 int expired = dvr_playback_calculate_expiredlen(ctx->playback.player);
2276 if (expired > time_offset) {
Wentao MA96f68962022-06-15 19:45:35 +08002277 DVR_WRAPPER_INFO("seek reset offset playback(sn:%ld) (off:%d expired:%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08002278 ctx->sn, time_offset, expired);
2279 time_offset = expired;
2280 }
2281 }
2282
wentao.maa22bc852022-10-13 12:18:06 +08002283 // This error is surpressed as the macro code is picked from kernel.
2284 // prefetch() here incurring self_assign is used to avoid some compiling
2285 // warnings.
2286 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002287 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
2288 segment_id = p_seg->seg_info.id;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002289
Wentao MA270dc0f2022-08-23 13:17:26 +08002290 if ((ctx->playback.obsolete.time + pre_off + p_seg->seg_info.duration) > time_offset)
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002291 break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002292
Wentao MA270dc0f2022-08-23 13:17:26 +08002293 last_segment_id = p_seg->seg_info.id;
2294 pre_off += p_seg->seg_info.duration;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002295 }
2296
2297 if (last_segment_id == segment_id) {
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002298 /*1.only one seg with id:0, 2.offset exceeds the total duration*/
2299 off = time_offset;
2300 } else if (ctx->playback.obsolete.time >= time_offset) {
2301 off = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002302 } else {
hualing chenda76fc52020-05-28 14:56:42 +08002303 off = time_offset - pre_off - ctx->playback.obsolete.time;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002304 }
2305
Wentao MA96f68962022-06-15 19:45:35 +08002306 DVR_WRAPPER_INFO("seek playback(sn:%ld) (seg:%lld, off:%d)\n",
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002307 ctx->sn, segment_id, off);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002308 error = dvr_playback_seek(ctx->playback.player, segment_id, off);
Wentao MA96f68962022-06-15 19:45:35 +08002309 DVR_WRAPPER_INFO("playback(sn:%ld) seeked(off:%d) (%d)\n", ctx->sn, time_offset, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002310
Gong Kefdb31922022-06-17 17:11:16 +08002311 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002312
2313 return error;
2314}
2315
2316int dvr_wrapper_update_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackPids_t *p_pids)
2317{
2318 DVR_WrapperCtx_t *ctx;
2319 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08002320 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002321
2322 DVR_RETURN_IF_FALSE(playback);
2323 DVR_RETURN_IF_FALSE(p_pids);
2324
2325 ctx = ctx_getPlayback((unsigned long)playback);
2326 DVR_RETURN_IF_FALSE(ctx);
2327
Gong Kefdb31922022-06-17 17:11:16 +08002328 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002329
Wentao MA96f68962022-06-15 19:45:35 +08002330 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) ...\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002331 ctx->sn,
2332 p_pids->video.pid, p_pids->video.format,
2333 p_pids->audio.pid, p_pids->audio.format);
Gong Kefdb31922022-06-17 17:11:16 +08002334 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002335
2336 ctx->playback.pids_req = *p_pids;
2337
2338 error = 0;
wentao.maa22bc852022-10-13 12:18:06 +08002339 // This error is surpressed as the macro code is picked from kernel.
2340 // prefetch() here incurring self_assign is used to avoid some compiling
2341 // warnings.
2342 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002343 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002344 /*should update the whole list of segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002345 /*if (p_seg->seg_info.id == ctx->current_segment_id)*/ {
2346 /*list_for_each_entry_from(p_seg, &ctx->segments, head)*/ {
2347 /*check update for pids*/
2348 if (memcmp(&p_seg->playback_info.pids, p_pids, sizeof(*p_pids)) != 0) {
2349 p_seg->playback_info.pids = *p_pids;
2350 error = dvr_playback_update_segment_pids(ctx->playback.player, p_seg->seg_info.id, p_pids);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002351 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08002352 DVR_WRAPPER_INFO("failed to playback(sn:%ld) update segment(id:%lld) pids (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08002353 ctx->sn, p_seg->seg_info.id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002354 /*do not break, let list updated*/
2355 }
2356 }
2357 }
2358 /*break;*/
2359 }
2360 }
2361
Wentao MA96f68962022-06-15 19:45:35 +08002362 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002363 ctx->sn,
2364 p_pids->video.pid, p_pids->video.format,
2365 p_pids->audio.pid, p_pids->audio.format,
2366 error);
2367
Gong Kefdb31922022-06-17 17:11:16 +08002368 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002369
2370 return error;
2371}
2372
hualing chena5f03222021-12-02 11:22:35 +08002373int dvr_wrapper_only_update_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackPids_t *p_pids)
2374{
2375 DVR_WrapperCtx_t *ctx;
2376 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08002377 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
hualing chena5f03222021-12-02 11:22:35 +08002378
2379 DVR_RETURN_IF_FALSE(playback);
2380 DVR_RETURN_IF_FALSE(p_pids);
2381
2382 ctx = ctx_getPlayback((unsigned long)playback);
2383 DVR_RETURN_IF_FALSE(ctx);
2384
Gong Kefdb31922022-06-17 17:11:16 +08002385 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002386
Wentao MA96f68962022-06-15 19:45:35 +08002387 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) ...\n",
hualing chena5f03222021-12-02 11:22:35 +08002388 ctx->sn,
2389 p_pids->video.pid, p_pids->video.format,
2390 p_pids->audio.pid, p_pids->audio.format);
Gong Kefdb31922022-06-17 17:11:16 +08002391 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002392
2393 ctx->playback.pids_req = *p_pids;
2394
2395 error = 0;
wentao.maa22bc852022-10-13 12:18:06 +08002396 // This error is surpressed as the macro code is picked from kernel.
2397 // prefetch() here incurring self_assign is used to avoid some compiling
2398 // warnings.
2399 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002400 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
hualing chena5f03222021-12-02 11:22:35 +08002401 /*should update the whole list of segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002402 /*if (p_seg->seg_info.id == ctx->current_segment_id)*/ {
2403 /*list_for_each_entry_from(p_seg, &ctx->segments, head)*/ {
2404 /*check update for pids*/
2405 if (memcmp(&p_seg->playback_info.pids, p_pids, sizeof(*p_pids)) != 0) {
2406 p_seg->playback_info.pids = *p_pids;
2407 error = dvr_playback_only_update_segment_pids(ctx->playback.player, p_seg->seg_info.id, p_pids);
hualing chena5f03222021-12-02 11:22:35 +08002408 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08002409 DVR_WRAPPER_INFO("failed to playback(sn:%ld) update segment(id:%lld) pids (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08002410 ctx->sn, p_seg->seg_info.id, error);
hualing chena5f03222021-12-02 11:22:35 +08002411 /*do not break, let list updated*/
2412 }
2413 }
2414 }
2415 /*break;*/
2416 }
2417 }
2418
Wentao MA96f68962022-06-15 19:45:35 +08002419 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) (%d)\n",
hualing chena5f03222021-12-02 11:22:35 +08002420 ctx->sn,
2421 p_pids->video.pid, p_pids->video.format,
2422 p_pids->audio.pid, p_pids->audio.format,
2423 error);
2424
Gong Kefdb31922022-06-17 17:11:16 +08002425 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002426
2427 return error;
2428}
2429
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002430int dvr_wrapper_get_playback_status(DVR_WrapperPlayback_t playback, DVR_WrapperPlaybackStatus_t *status)
2431{
2432 DVR_WrapperCtx_t *ctx;
2433 DVR_WrapperPlaybackStatus_t s;
2434 DVR_PlaybackStatus_t play_status;
2435 int error;
2436
2437 DVR_RETURN_IF_FALSE(playback);
2438 DVR_RETURN_IF_FALSE(status);
2439
2440 ctx = ctx_getPlayback((unsigned long)playback);
2441 DVR_RETURN_IF_FALSE(ctx);
2442
Gong Kefdb31922022-06-17 17:11:16 +08002443 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002444
Wentao MA96f68962022-06-15 19:45:35 +08002445 DVR_WRAPPER_INFO("get playback(sn:%ld) status ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002446 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002447
2448 error = dvr_playback_get_status(ctx->playback.player, &play_status);
Wentao MA96f68962022-06-15 19:45:35 +08002449 DVR_WRAPPER_INFO("playback(sn:%ld) get status (%d)\n", ctx->sn, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002450
2451 ctx->playback.seg_status = play_status;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002452 error = process_generatePlaybackStatus(ctx, &s);
2453
hualing chenb5cd42e2020-04-15 17:03:34 +08002454 if (ctx->playback.reach_end == DVR_TRUE && ctx->playback.param_open.is_timeshift == DVR_FALSE) {
2455 //reach end need set full time to cur.so app can exist playback.
Wentao MA96f68962022-06-15 19:45:35 +08002456 DVR_WRAPPER_INFO("set cur time to full time, reach end occur");
hualing chenb5cd42e2020-04-15 17:03:34 +08002457 s.info_cur.time = s.info_full.time;
2458 }
Wentao MA270dc0f2022-08-23 13:17:26 +08002459 DVR_WRAPPER_INFO("playback(sn:%ld) state/cur/full/obsolete(%d/%ld/%ld/%ld) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002460 ctx->sn,
2461 s.state,
2462 s.info_cur.time,
2463 s.info_full.time,
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002464 s.info_obsolete.time,
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002465 error);
2466
2467 *status = s;
2468
Gong Kefdb31922022-06-17 17:11:16 +08002469 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002470
2471 return error;
2472}
2473
hualing chen266b9502020-04-04 17:39:39 +08002474int dvr_wrapper_set_playback_secure_buffer (DVR_WrapperPlayback_t playback, uint8_t *p_secure_buf, uint32_t len)
2475{
2476 DVR_WrapperCtx_t *ctx;
2477 int error;
2478
2479 DVR_RETURN_IF_FALSE(playback);
2480 DVR_RETURN_IF_FALSE(p_secure_buf);
2481
2482 ctx = ctx_getPlayback((unsigned long)playback);
2483 DVR_RETURN_IF_FALSE(ctx);
2484
Gong Kefdb31922022-06-17 17:11:16 +08002485 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002486 error = dvr_playback_set_secure_buffer(ctx->playback.player, p_secure_buf, len);
Gong Kefdb31922022-06-17 17:11:16 +08002487 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002488 return error;
2489}
2490
2491int dvr_wrapper_set_playback_decrypt_callback (DVR_WrapperPlayback_t playback, DVR_CryptoFunction_t func, void *userdata)
2492{
2493 DVR_WrapperCtx_t *ctx;
2494 int error;
2495
2496 DVR_RETURN_IF_FALSE(playback);
2497 DVR_RETURN_IF_FALSE(func);
2498
2499 ctx = ctx_getPlayback((unsigned long)playback);
2500 DVR_RETURN_IF_FALSE(ctx);
2501
Gong Kefdb31922022-06-17 17:11:16 +08002502 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002503 error = dvr_playback_set_decrypt_callback(ctx->playback.player, func, userdata);
Gong Kefdb31922022-06-17 17:11:16 +08002504 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002505 return error;
2506}
2507
Zhiqiang Han620b9252021-11-09 14:23:20 +08002508int dvr_wrapper_segment_del_by_location (const char *location)
2509{
2510 char fpath[DVR_MAX_LOCATION_SIZE];
2511
2512 DVR_RETURN_IF_FALSE(location);
2513
2514 /*del the stats file*/
2515 sprintf(fpath, "%s.stats", location);
2516 unlink(fpath);
2517
2518 return dvr_segment_del_by_location(location);
2519}
2520
2521int dvr_wrapper_segment_get_info_by_location (const char *location, DVR_WrapperInfo_t *p_info)
2522{
2523 FILE *fp;
2524 char fpath[DVR_MAX_LOCATION_SIZE];
2525
2526 DVR_RETURN_IF_FALSE(location);
2527 DVR_RETURN_IF_FALSE(p_info);
2528
2529 if (p_info)
2530 memset(p_info, 0, sizeof(p_info[0]));
2531
2532 memset(fpath, 0, sizeof(fpath));
2533 sprintf(fpath, "%s.stats", location);
2534
2535 /*stats file exists*/
2536 if ((fp = fopen(fpath, "r"))) {
2537 char buf[256];
2538
2539 if (fgets(buf, sizeof(buf), fp) != NULL
2540 && (sscanf(buf, ":%llu:%lu:%u",
2541 &p_info->size,
2542 &p_info->time,
2543 &p_info->pkts) == 3)) {
2544 fclose(fp);
Wentao MA96f68962022-06-15 19:45:35 +08002545 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 +08002546 return DVR_SUCCESS;
2547 }
Zhiqiang Hanb9785922021-11-26 18:47:39 +08002548 fclose(fp);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002549 }
2550
2551 /*fallback, slow on mass files*/
Wentao MA96f68962022-06-15 19:45:35 +08002552 DVR_WRAPPER_INFO("rec '%s.stats' invalid.\n", location);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002553
2554 int error;
2555 uint32_t n_ids;
2556 uint64_t *p_ids;
Zhiqiang Han620b9252021-11-09 14:23:20 +08002557
hualing chen8aed9582021-12-24 17:59:56 +08002558 error = dvr_segment_get_list(location, &n_ids, &p_ids);
hualing chenb9a02922021-12-14 11:29:47 +08002559
Zhiqiang Han620b9252021-11-09 14:23:20 +08002560 if (!error) {
2561 int i;
hualing chenb9a02922021-12-14 11:29:47 +08002562 struct list_head info_list; /**< segment list head*/
2563 INIT_LIST_HEAD(&info_list);
2564
2565 //we need free info list buf when we used end.
hualing chen8aed9582021-12-24 17:59:56 +08002566 error = dvr_segment_get_allInfo(location, &info_list);
2567 if (error == DVR_FAILURE) {
wentao.maa210e5e2022-10-12 16:10:03 +08002568 DVR_RecordSegmentInfo_t info = { .id = 0, .nb_pids = 0,
2569 .pids = {0}, .duration = 0, .size = 0, .nb_packets = 0 };
hualing chenb9a02922021-12-14 11:29:47 +08002570
2571 memset(&info, 0, sizeof(info));
2572 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08002573 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chen8aed9582021-12-24 17:59:56 +08002574 location, 0, error);
hualing chenb9a02922021-12-14 11:29:47 +08002575
wentao.maf57dd232022-10-08 16:07:29 +08002576 // Tainted data issue originating from fgets seem false positive, so we
2577 // just suppress it here.
2578 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08002579 for (i = 0; i < n_ids; i++) {
hualing chen8aed9582021-12-24 17:59:56 +08002580 error = dvr_segment_get_info(location, p_ids[i], &info);
hualing chenb9a02922021-12-14 11:29:47 +08002581 if (!error) {
2582 p_info->size += info.size;
2583 p_info->time += info.duration;
2584 p_info->pkts += info.nb_packets;
2585 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002586 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chenb9a02922021-12-14 11:29:47 +08002587 break;
2588 }
2589 }
2590 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002591 DVR_WRAPPER_INFO("get list segment_nb::%d",n_ids);
wentao.maf57dd232022-10-08 16:07:29 +08002592 // Tainted data issue originating from fgets seem false positive, so we
2593 // just suppress it here.
2594 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08002595 for (i = 0; i < n_ids; i++) {
2596
2597 DVR_RecordSegmentInfo_t *seg_info;
2598 DVR_PlaybackSegmentFlag_t flags;
2599 int found = 0;
wentao.maa22bc852022-10-13 12:18:06 +08002600 // This error is surpressed as the macro code is picked from kernel.
2601 // prefetch() here incurring self_assign is used to avoid some compiling
2602 // warnings.
2603 // coverity[self_assign]
hualing chenb9a02922021-12-14 11:29:47 +08002604 list_for_each_entry(seg_info, &info_list, head)
2605 {
hualing chen8aed9582021-12-24 17:59:56 +08002606 if (seg_info->id == p_ids[i]) {
hualing chenb9a02922021-12-14 11:29:47 +08002607 found = 1;
2608 break;
2609 }
2610 }
2611 if (!found) {
Wentao MA96f68962022-06-15 19:45:35 +08002612 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 +08002613 if (p_ids[i] == n_ids - 1) {
wentao.maa210e5e2022-10-12 16:10:03 +08002614 DVR_RecordSegmentInfo_t info = { .id = 0, .nb_pids = 0,
2615 .pids = {0}, .duration = 0, .size = 0, .nb_packets = 0 };
Wentao MA96f68962022-06-15 19:45:35 +08002616 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 +08002617 error = dvr_segment_get_info(location, p_ids[i], &info);
2618 if (!error) {
2619 p_info->size += info.size;
2620 p_info->time += info.duration;
2621 p_info->pkts += info.nb_packets;
2622 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002623 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chen8aed9582021-12-24 17:59:56 +08002624 break;
2625 }
2626 }
hualing chenb9a02922021-12-14 11:29:47 +08002627 continue;
2628 }
2629
2630 if (!error) {
2631 p_info->size += seg_info->size;
2632 p_info->time += seg_info->duration;
2633 p_info->pkts += seg_info->nb_packets;
2634 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002635 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chenb9a02922021-12-14 11:29:47 +08002636 break;
2637 }
2638 }
2639 //free list
2640 DVR_RecordSegmentInfo_t *segment = NULL;
2641 DVR_RecordSegmentInfo_t *segment_tmp = NULL;
2642 list_for_each_entry_safe(segment, segment_tmp, &info_list, head)
2643 {
2644 if (segment) {
2645 list_del(&segment->head);
2646 free(segment);
2647 }
2648 }
2649 }
2650 free(p_ids);
Zhiqiang Hanb9785922021-11-26 18:47:39 +08002651 } else {
2652 n_ids = 0;
Zhiqiang Han620b9252021-11-09 14:23:20 +08002653 }
Wentao MA96f68962022-06-15 19:45:35 +08002654 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 +08002655
2656 return (error)? DVR_FAILURE : DVR_SUCCESS;
2657}
2658
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002659static DVR_Result_t wrapper_record_event_handler(DVR_RecordEvent_t event, void *params, void *userdata)
2660{
wentao.maa210e5e2022-10-12 16:10:03 +08002661 DVR_WrapperEventCtx_t evt = {
2662 .sn = (unsigned long)userdata,
2663 .type = W_REC,
2664 .record.event = event,
2665 .record.status = *(DVR_RecordStatus_t *)params
2666 };
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002667
2668 DVR_RETURN_IF_FALSE(userdata);
2669
Wentao MA96f68962022-06-15 19:45:35 +08002670 DVR_WRAPPER_INFO("evt[sn:%ld, record, evt:0x%x]\n", evt.sn, evt.record.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002671 return ctx_addRecordEvent(&evt);
2672}
2673
2674static DVR_Result_t wrapper_playback_event_handler(DVR_PlaybackEvent_t event, void *params, void *userdata)
2675{
wentao.maa210e5e2022-10-12 16:10:03 +08002676 DVR_WrapperEventCtx_t evt = {
2677 .sn = (unsigned long)userdata,
2678 .type = W_PLAYBACK,
2679 .playback.event = event,
2680 .playback.status = *(DVR_Play_Notify_t *)params
2681 };
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002682
2683 DVR_RETURN_IF_FALSE(userdata);
2684
2685 evt.sn = (unsigned long)userdata;
2686 evt.type = W_PLAYBACK;
2687 evt.playback.event = event;
2688 evt.playback.status = *(DVR_Play_Notify_t *)params;
Wentao MA9a164002022-08-29 11:20:24 +08002689 DVR_WRAPPER_INFO("evt[sn:%ld, playback, evt:0x%x]\n", evt.sn, evt.playback.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002690 return ctx_addPlaybackEvent(&evt);
2691}
2692
2693static inline int process_notifyRecord(DVR_WrapperCtx_t *ctx, DVR_RecordEvent_t evt, DVR_WrapperRecordStatus_t *status)
2694{
Wentao MA270dc0f2022-08-23 13:17:26 +08002695 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 +08002696 ctx->sn,
2697 evt,
2698 status->info.time,
2699 status->info.size,
2700 status->info.pkts,
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002701 status->info_obsolete.time,
2702 status->info_obsolete.size,
2703 status->info_obsolete.pkts);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002704
2705 if (ctx->record.event_fn)
2706 return ctx->record.event_fn(evt, status, ctx->record.event_userdata);
2707 return 0;
2708}
2709
Zhiqiang Han620b9252021-11-09 14:23:20 +08002710static int wrapper_saveRecordStatistics(const char *location, DVR_WrapperRecordStatus_t *p_status)
2711{
2712 FILE *fp;
2713 char fpath[DVR_MAX_LOCATION_SIZE];
2714
2715 DVR_RETURN_IF_FALSE(location);
2716 DVR_RETURN_IF_FALSE(p_status);
2717
2718 sprintf(fpath, "%s.stats", location);
2719
2720 /*stats file*/
2721 if ((fp = fopen(fpath, "w"))) {
2722 char buf[256];
2723 snprintf(buf, sizeof(buf), ":%llu:%lu:%u\n",
2724 p_status->info.size - p_status->info_obsolete.size,
2725 p_status->info.time - p_status->info_obsolete.time,
2726 p_status->info.pkts - p_status->info_obsolete.pkts);
2727 fputs(buf, fp);
Zhiqiang Handc3bfe52022-07-07 10:48:39 +08002728 fflush(fp);
2729 fsync(fileno(fp));
Zhiqiang Han620b9252021-11-09 14:23:20 +08002730 fclose(fp);
2731 return DVR_SUCCESS;
2732 }
2733
2734 return DVR_FAILURE;
2735}
2736
2737
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002738static inline int record_startNextSegment(DVR_WrapperCtx_t *ctx)
2739{
2740 DVR_RecordStartParams_t param;
2741 DVR_RecordSegmentInfo_t seg_info;
2742 int i;
2743 int error;
2744
2745 memcpy(&param, &ctx->record.param_update, sizeof(param));
2746 memset(&ctx->record.param_update.segment, 0, sizeof(ctx->record.param_update.segment));
2747 ctx->record.param_update.segment.segment_id = ctx->record.next_segment_id++;
2748 for (i = 0; i < param.segment.nb_pids; i++) {
2749 if (param.segment.pid_action[i] != DVR_RECORD_PID_CLOSE) {
2750 ctx->record.param_update.segment.pids[ctx->record.param_update.segment.nb_pids] = param.segment.pids[i];
2751 ctx->record.param_update.segment.pid_action[ctx->record.param_update.segment.nb_pids] = DVR_RECORD_PID_KEEP;
2752 ctx->record.param_update.segment.nb_pids++;
2753 }
2754 }
2755 error = dvr_record_next_segment(ctx->record.recorder, &ctx->record.param_update, &seg_info);
2756 {
2757 DVR_RecordSegmentInfo_t new_seg_info =
2758 { .id = ctx->record.param_update.segment.segment_id, };
2759 wrapper_updateRecordSegment(ctx, &seg_info, U_ALL);
2760 wrapper_addRecordSegment(ctx, &new_seg_info);
2761 }
2762
Wentao MA96f68962022-06-15 19:45:35 +08002763 DVR_WRAPPER_INFO("record next segment(%llu)=(%d)\n", ctx->record.param_update.segment.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002764 return error;
2765}
2766
Wentao MA270dc0f2022-08-23 13:17:26 +08002767static inline int record_removeSegment(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordSegmentInfo_t *p_seg)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002768{
Wentao MA270dc0f2022-08-23 13:17:26 +08002769 return wrapper_removeRecordSegment(ctx, p_seg);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002770}
2771
2772/*should run periodically to update the current status*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002773static int process_generateRecordStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordStatus_t *status)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002774{
2775 /*the current seg is not covered in the statistics*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002776 DVR_WrapperRecordSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002777
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002778 /*re-calculate the all segments*/
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002779 memset(&ctx->record.status, 0, sizeof(ctx->record.status));
2780
2781 ctx->record.status.state = ctx->record.seg_status.state;
2782 ctx->record.status.pids.nb_pids = ctx->record.seg_status.info.nb_pids;
2783 memcpy(ctx->record.status.pids.pids,
2784 ctx->record.seg_status.info.pids,
2785 sizeof(ctx->record.status.pids.pids));
2786 ctx->current_segment_id = ctx->record.seg_status.info.id;
2787
wentao.maa22bc852022-10-13 12:18:06 +08002788 // This error is surpressed as the macro code is picked from kernel.
2789 // prefetch() here incurring self_assign is used to avoid some compiling
2790 // warnings.
2791 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002792 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
2793 if (p_seg->info.id != ctx->record.seg_status.info.id) {
2794 ctx->record.status.info.time += p_seg->info.duration;
2795 ctx->record.status.info.size += p_seg->info.size;
2796 ctx->record.status.info.pkts += p_seg->info.nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002797 }
2798 }
2799
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002800 ctx->record.status.info_obsolete = ctx->record.obsolete;
2801
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002802 wrapper_updateRecordSegment(ctx, &ctx->record.seg_status.info, U_ALL);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002803
2804 if (status) {
2805 *status = ctx->record.status;
2806 status->info.time += ctx->record.seg_status.info.duration;
2807 status->info.size += ctx->record.seg_status.info.size;
2808 status->info.pkts += ctx->record.seg_status.info.nb_packets;
2809 }
2810
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002811 return DVR_SUCCESS;
2812}
2813
2814
2815static int process_handleRecordEvent(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
2816{
2817 DVR_WrapperRecordStatus_t status;
2818
2819 memset(&status, 0, sizeof(status));
2820
Wentao MA96f68962022-06-15 19:45:35 +08002821 DVR_WRAPPER_INFO("evt (sn:%ld) 0x%x (state:%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002822 evt->sn, evt->record.event, evt->record.status.state);
hualing chend3b55ab2021-05-06 09:56:27 +08002823 if (ctx->record.param_update.segment.segment_id != evt->record.status.info.id) {
Wentao MA96f68962022-06-15 19:45:35 +08002824 DVR_WRAPPER_INFO("evt (sn:%ld) cur id:0x%x (event id:%d)\n",
Gong Ke2a0ebbe2021-05-25 15:22:50 +08002825 evt->sn, (int)ctx->record.param_update.segment.segment_id, (int)evt->record.status.info.id);
hualing chend3b55ab2021-05-06 09:56:27 +08002826 return 0;
2827 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002828 switch (evt->record.event)
2829 {
2830 case DVR_RECORD_EVENT_STATUS:
2831 {
2832 switch (evt->record.status.state)
2833 {
2834 case DVR_RECORD_STATE_OPENED:
2835 case DVR_RECORD_STATE_CLOSED:
2836 {
2837 ctx->record.seg_status = evt->record.status;
2838
2839 status.state = evt->record.status.state;
2840 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002841 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002842 } break;
2843 case DVR_RECORD_STATE_STARTED:
2844 {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002845 ctx->record.seg_status = evt->record.status;
2846
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002847 process_generateRecordStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002848 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002849 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002850
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002851 /*restart to next segment*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002852 if (ctx->record.param_open.segment_size
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002853 && evt->record.status.info.size >= ctx->record.param_open.segment_size) {
Wentao MA96f68962022-06-15 19:45:35 +08002854 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 +08002855 ctx->sn,
2856 evt->record.status.info.size,
2857 ctx->record.param_open.segment_size);
Zhiqiang Hand977e972020-05-11 11:30:47 +08002858 if (record_startNextSegment(ctx) != DVR_SUCCESS) {
2859 /*should notify the recording's stop*/
2860 int error = dvr_record_close(ctx->record.recorder);
Wentao MA96f68962022-06-15 19:45:35 +08002861 DVR_WRAPPER_INFO("stop record(%lu)=%d, failed to start new segment for recording.",
Zhiqiang Hand977e972020-05-11 11:30:47 +08002862 ctx->sn, error);
2863 status.state = DVR_RECORD_STATE_CLOSED;
2864 process_notifyRecord(ctx, DVR_RECORD_EVENT_WRITE_ERROR, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002865 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Hand977e972020-05-11 11:30:47 +08002866 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002867 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002868
2869 if (ctx->record.param_open.is_timeshift
2870 && ctx->record.param_open.max_time
2871 && status.info.time >= ctx->record.param_open.max_time) {
Wentao MA270dc0f2022-08-23 13:17:26 +08002872 DVR_WrapperRecordSegmentInfo_t *p_seg;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002873
2874 /*as the player do not support null playlist,
2875 there must be one segment existed at any time,
2876 we have to keep two segments before remove one*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002877 p_seg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
2878 if (p_seg == list_first_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head)) {
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002879 /*only one segment, waiting for more*/
Wentao MA96f68962022-06-15 19:45:35 +08002880 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 +08002881 status.info.size,
2882 ctx->record.param_open.max_time,
2883 ctx->record.param_open.segment_size);
2884 } else {
2885 /*timeshifting, remove the 1st segment and notify the player*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002886 record_removeSegment(ctx, p_seg);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002887
2888 process_generateRecordStatus(ctx, &status);
2889 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002890 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002891 }
2892 }
2893
Wentao MAf4072032022-06-30 13:50:45 +08002894 const loff_t actual_size = status.info.size;
2895 const loff_t max_size = ctx->record.param_open.max_size;
2896 const loff_t segment_size = ctx->record.param_open.segment_size;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002897
Wentao MAf4072032022-06-30 13:50:45 +08002898 if (ctx->record.param_open.is_timeshift && max_size) {
2899 if (actual_size >= max_size) {
Wentao MA270dc0f2022-08-23 13:17:26 +08002900 DVR_WrapperRecordSegmentInfo_t *p_seg;
Wentao MAf4072032022-06-30 13:50:45 +08002901 /*as the player do not support null playlist,
2902 there must be one segment existed at any time,
2903 we have to keep two segments before remove one*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002904 p_seg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
2905 if (p_seg == list_first_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head)) {
Wentao MAf4072032022-06-30 13:50:45 +08002906 /*only one segment, waiting for more*/
2907 DVR_WRAPPER_INFO("warning: the size(%lld) of record < max size of segment(%lld)\n",
2908 actual_size, segment_size);
2909 } else {
Wentao MA270dc0f2022-08-23 13:17:26 +08002910 record_removeSegment(ctx, p_seg);
Wentao MAf4072032022-06-30 13:50:45 +08002911
2912 process_generateRecordStatus(ctx, &status);
2913 process_notifyRecord(ctx, evt->record.event, &status);
2914 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
2915 }
2916 if (actual_size >= max_size + segment_size/2) {
2917 dvr_record_discard_coming_data(ctx->record.recorder,DVR_TRUE);
2918 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002919 } else {
Wentao MAf4072032022-06-30 13:50:45 +08002920 dvr_record_discard_coming_data(ctx->record.recorder,DVR_FALSE);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002921 }
2922 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002923 } break;
2924 case DVR_RECORD_STATE_STOPPED:
2925 {
2926 ctx->record.seg_status = evt->record.status;
2927
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002928 process_generateRecordStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002929 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002930 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002931 } break;
2932 default:
2933 break;
2934 }
2935 } break;
hualing chen4b7c15d2020-04-07 16:13:48 +08002936 case DVR_RECORD_EVENT_WRITE_ERROR: {
2937 ctx->record.seg_status = evt->record.status;
2938 status.state = evt->record.status.state;
2939 process_notifyRecord(ctx, evt->record.event, &status);
2940 }break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002941 default:
2942 break;
2943 }
2944 return DVR_SUCCESS;
2945}
2946
2947static inline int process_notifyPlayback(DVR_WrapperCtx_t *ctx, DVR_PlaybackEvent_t evt, DVR_WrapperPlaybackStatus_t *status)
2948{
Wentao MA270dc0f2022-08-23 13:17:26 +08002949 DVR_WRAPPER_INFO("notify(sn:%ld) evt(0x%x) statistics:state/cur/full/obsolete(%d/%ld/%ld/%ld)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002950 ctx->sn,
2951 evt,
2952 status->state,
2953 status->info_cur.time,
2954 status->info_full.time,
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002955 status->info_obsolete.time);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002956
2957 if (ctx->playback.event_fn)
2958 return ctx->playback.event_fn(evt, status, ctx->playback.event_userdata);
2959 return 0;
2960}
2961
2962/*should run periodically to update the current status*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002963static int process_generatePlaybackStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperPlaybackStatus_t *status)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002964{
2965 /*the current seg is not covered in the statistics*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002966 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002967
2968 memset(&ctx->playback.status, 0, sizeof(ctx->playback.status));
2969 ctx->playback.status.pids = ctx->playback.pids_req;
2970
2971 ctx->playback.status.state = ctx->playback.seg_status.state;
2972 ctx->playback.status.speed = ctx->playback.seg_status.speed;
2973 ctx->playback.status.flags = ctx->playback.seg_status.flags;
2974 ctx->current_segment_id = ctx->playback.seg_status.segment_id;
2975
wentao.maa22bc852022-10-13 12:18:06 +08002976 // This error is surpressed as the macro code is picked from kernel.
2977 // prefetch() here incurring self_assign is used to avoid some compiling
2978 // warnings.
2979 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002980 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
2981 if (p_seg->seg_info.id == ctx->playback.seg_status.segment_id) {
2982 DVR_WRAPPER_INFO("calculate cur time :[%lld]time[%d]\n", p_seg->seg_info.id, p_seg->seg_info.duration);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002983 break;
hualing chen451c8f72022-03-09 13:05:52 +08002984 }
2985
Wentao MA270dc0f2022-08-23 13:17:26 +08002986 ctx->playback.status.info_cur.time += p_seg->seg_info.duration;
2987 ctx->playback.status.info_cur.size += p_seg->seg_info.size;
2988 ctx->playback.status.info_cur.pkts += p_seg->seg_info.nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002989 }
wentao.maa22bc852022-10-13 12:18:06 +08002990 // This error is surpressed as the macro code is picked from kernel.
2991 // prefetch() here incurring self_assign is used to avoid some compiling
2992 // warnings.
2993 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002994 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
2995 ctx->playback.status.info_full.time += p_seg->seg_info.duration;
2996 ctx->playback.status.info_full.size += p_seg->seg_info.size;
2997 ctx->playback.status.info_full.pkts += p_seg->seg_info.nb_packets;
2998 DVR_WRAPPER_INFO("calculate full time :[%lld]time[%d]\n", p_seg->seg_info.id, p_seg->seg_info.duration);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002999 }
3000
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08003001 if (status) {
3002 *status = ctx->playback.status;
3003 /*deal with current, lack size and pkts with the current*/
3004 status->info_cur.time += ctx->playback.seg_status.time_cur;
hualing chen56c0a162022-01-27 17:01:50 +08003005 //get last segment id
Wentao MA270dc0f2022-08-23 13:17:26 +08003006 DVR_WrapperRecordSegmentInfo_t *p_seg;
hualing chen56c0a162022-01-27 17:01:50 +08003007
Wentao MA270dc0f2022-08-23 13:17:26 +08003008 p_seg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
3009 if (ctx->playback.tf_full == DVR_TRUE && p_seg->info.id == ctx->current_segment_id) {
hualing chen56c0a162022-01-27 17:01:50 +08003010 status->disguised_info_obsolete.time = ctx->playback.obsolete.time + ctx->playback.seg_status.time_cur;
3011 status->info_obsolete.time = ctx->playback.obsolete.time;
Wentao MA270dc0f2022-08-23 13:17:26 +08003012 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 +08003013 }
3014 else
3015 {
Wentao MA270dc0f2022-08-23 13:17:26 +08003016 DVR_WRAPPER_INFO("warning not change start time :ctx->playback.tf_full[%d]id[%lld] [%lld] cur[%d]\n",ctx->playback.tf_full , p_seg->info.id, ctx->current_segment_id, status->info_cur.time);
hualing chen56c0a162022-01-27 17:01:50 +08003017 status->info_obsolete.time = ctx->playback.obsolete.time;
3018 status->disguised_info_obsolete.time = ctx->playback.obsolete.time;
3019 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08003020 }
3021
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003022 return DVR_SUCCESS;
3023}
3024
3025static int process_handlePlaybackEvent(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
3026{
Wentao MA96f68962022-06-15 19:45:35 +08003027 DVR_WRAPPER_INFO("evt (sn:%ld) 0x%x (state:%d) cur(%lld:%u/%u)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003028 evt->sn, evt->playback.event,
3029 evt->playback.status.play_status.state,
3030 evt->playback.status.play_status.segment_id,
3031 evt->playback.status.play_status.time_cur,
3032 evt->playback.status.play_status.time_end);
3033
3034 /*evt PLAYTIME will break the last logic, do not save*/
hualing chene3797f02021-01-13 14:53:28 +08003035 if (evt->playback.event != DVR_PLAYBACK_EVENT_NOTIFY_PLAYTIME
3036 && evt->playback.event != DVR_PLAYBACK_EVENT_NODATA
3037 && evt->playback.event != DVR_PLAYBACK_EVENT_DATARESUME
3038 )
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003039 ctx->playback.last_event = evt->playback.event;
3040
3041 switch (evt->playback.event)
3042 {
3043 case DVR_PLAYBACK_EVENT_FIRST_FRAME:
3044 case DVR_PLAYBACK_EVENT_REACHED_END:
3045 case DVR_PLAYBACK_EVENT_TRANSITION_OK:
3046 case DVR_PLAYBACK_EVENT_NOTIFY_PLAYTIME:
hualing chenb5cd42e2020-04-15 17:03:34 +08003047 case DVR_PLAYBACK_EVENT_ERROR:
hualing chenf291cf32020-06-18 10:50:30 +08003048 case DVR_PLAYBACK_EVENT_REACHED_BEGIN:
hualing chene3797f02021-01-13 14:53:28 +08003049 case DVR_PLAYBACK_EVENT_NODATA:
3050 case DVR_PLAYBACK_EVENT_DATARESUME:
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003051 {
3052 DVR_WrapperPlaybackStatus_t status;
3053
3054 /*copy status of segment*/
3055 ctx->playback.seg_status = evt->playback.status.play_status;
3056
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08003057 /*generate status of the whole playback*/
3058 process_generatePlaybackStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003059
3060 if (evt->playback.event == DVR_PLAYBACK_EVENT_REACHED_END) {
Wentao MA96f68962022-06-15 19:45:35 +08003061 DVR_WRAPPER_INFO("playback(sn:%ld) event:0x%x\n", evt->sn, evt->playback.event);
hualing chenb9b358a2021-08-17 15:06:36 +08003062 if (ctx->playback.param_open.is_timeshift
3063 || ctx_isPlay_recording(ctx->playback.param_open.location)) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003064 /*wait for more data in recording*/
Zhiqiang Han31846002021-11-04 10:49:06 +08003065 }
3066 /*trust the low level, make NO check.
3067 As this evt is changed to only once due to some operations(paused) in low level.
3068 else if ((status.info_cur.time + DVR_PLAYBACK_END_GAP) >= ctx->playback.status.info_full.time) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003069 process_notifyPlayback(ctx, evt->playback.event, &status);
Zhiqiang Han31846002021-11-04 10:49:06 +08003070 }
3071 */
3072 else {
3073 process_notifyPlayback(ctx, evt->playback.event, &status);
hualing chenb5cd42e2020-04-15 17:03:34 +08003074 ctx->playback.reach_end = DVR_TRUE;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003075 }
hualing chenf291cf32020-06-18 10:50:30 +08003076 } else if (evt->playback.event != DVR_PLAYBACK_EVENT_REACHED_BEGIN) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003077 process_notifyPlayback(ctx, evt->playback.event, &status);
3078 }
3079 } break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003080 case DVR_PLAYBACK_EVENT_TRANSITION_FAILED:
3081 case DVR_PLAYBACK_EVENT_KEY_FAILURE:
3082 case DVR_PLAYBACK_EVENT_NO_KEY:
3083 {
Wentao MA96f68962022-06-15 19:45:35 +08003084 DVR_WRAPPER_INFO("playback(sn:%ld) error event:0x%x\n", evt->sn, evt->playback.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003085 } break;
3086 default:
3087 {
Wentao MA96f68962022-06-15 19:45:35 +08003088 DVR_WRAPPER_INFO("playback(sn:%ld) unknown event:0x%x\n", evt->sn, evt->playback.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003089 } break;
3090 }
3091 return 0;
3092}
3093
3094static inline int process_handleEvents(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
3095{
3096 return (evt->type == W_REC)? process_handleRecordEvent(evt, ctx) : process_handlePlaybackEvent(evt, ctx);
3097}
3098
Wentao MA96f68962022-06-15 19:45:35 +08003099int dvr_wrapper_set_log_level (int level)
3100{
3101 if (level<LOG_LV_DEFAULT || level>LOG_LV_FATAL) {
3102 DVR_WRAPPER_ERROR("Invalid dvr log level:%d", g_dvr_log_level);
3103 return DVR_FAILURE;
3104 }
3105 g_dvr_log_level = level;
3106 DVR_WRAPPER_INFO("New dvr log level:%d", g_dvr_log_level);
3107 return DVR_SUCCESS;
3108}
3109
Wentao MA5629ad82022-08-24 10:03:02 +08003110int dvr_wrapper_set_ac4_preselection_id(DVR_WrapperPlayback_t playback, int presel_id)
3111{
3112 DVR_WrapperCtx_t *ctx;
3113 int error;
3114
3115 DVR_RETURN_IF_FALSE(playback==NULL);
3116
3117 ctx = ctx_getPlayback((unsigned long)playback);
3118 DVR_RETURN_IF_FALSE(ctx);
3119
3120 wrapper_mutex_lock(&ctx->wrapper_lock);
3121
3122 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
3123
3124 DVR_WRAPPER_INFO("set ac4 preselection id: %d", presel_id);
3125 error = dvr_playback_set_ac4_preselection_id(ctx->playback.player, presel_id);
3126
3127 wrapper_mutex_unlock(&ctx->wrapper_lock);
3128
3129 return error;
3130}
3131