blob: ef2399f4573c7b7cbda0918e6424d596010237e5 [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"
wentao.ma9009aaa2022-10-25 14:26:33 +080016#include "dvr_utils.h"
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080017
18#include "AmTsPlayer.h"
19
20#include "list.h"
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080021
22#include "dvr_wrapper.h"
23
Wentao MA96f68962022-06-15 19:45:35 +080024#define WRAPPER_LOG_TAG "libdvr-wrapper"
25#define DVR_WRAPPER_DEBUG(...) DVR_LOG_PRINT(LOG_LV_DEBUG, WRAPPER_LOG_TAG, __VA_ARGS__)
26#define DVR_WRAPPER_INFO(...) DVR_LOG_PRINT(LOG_LV_INFO, WRAPPER_LOG_TAG, __VA_ARGS__)
27#define DVR_WRAPPER_WARN(...) DVR_LOG_PRINT(LOG_LV_WARN, WRAPPER_LOG_TAG, __VA_ARGS__)
28#define DVR_WRAPPER_ERROR(...) DVR_LOG_PRINT(LOG_LV_ERROR, WRAPPER_LOG_TAG, __VA_ARGS__)
29#define DVR_WRAPPER_FATAL(...) DVR_LOG_PRINT(LOG_LV_FATAL, WRAPPER_LOG_TAG, __VA_ARGS__)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080030
31/*duration of data to resume if paused with EVT_REACHED_END in timeshifting*/
hualing chen2932d372020-04-29 13:44:00 +080032#define TIMESHIFT_DATA_DURATION_TO_RESUME (600)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080033/*a tolerant gap*/
34#define DVR_PLAYBACK_END_GAP (1000)
35
Wentao MA96f68962022-06-15 19:45:35 +080036int g_dvr_log_level = LOG_LV_DEFAULT;
37
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080038enum {
39 W_REC = 1,
40 W_PLAYBACK = 2,
41};
42
43enum {
44 U_PIDS = 0x01,
45 U_STAT = 0x02,
46 U_ALL = U_PIDS | U_STAT,
47};
48
49typedef struct {
Gong Kefdb31922022-06-17 17:11:16 +080050 pthread_mutex_t lock;
51 pthread_cond_t cond;
52 int inited;
53 int locked;
54} DVR_WrapperMutex_t;
55
56static void
57wrapper_mutex_init (DVR_WrapperMutex_t *lock)
58{
59 pthread_condattr_t cattr;
60
Zhiqiang Han2259da32022-07-07 15:52:58 +080061 if (lock->inited)
Gong Kefdb31922022-06-17 17:11:16 +080062 return;
63
64 pthread_mutex_init(&lock->lock, NULL);
65
66 pthread_condattr_init(&cattr);
67 pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
68 pthread_cond_init(&lock->cond, &cattr);
69 pthread_condattr_destroy(&cattr);
70
wentao.maa22bc852022-10-13 12:18:06 +080071 // It is not necessary to protect code block below with
72 // DVR_WrapperMutex_t.lock, so the following annotation
wentao.mafd5283f2022-10-14 09:51:13 +080073 // is given to suppress related Coverity complaint.
wentao.maa22bc852022-10-13 12:18:06 +080074 // coverity[missing_lock]
Gong Kefdb31922022-06-17 17:11:16 +080075 lock->locked = 0;
76 lock->inited = 1;
77}
78
79static int
80wrapper_mutex_lock (DVR_WrapperMutex_t *lock)
81{
82 pthread_mutex_lock(&lock->lock);
wentao.maa22bc852022-10-13 12:18:06 +080083 // This couldn't be a infinite loop as Coverity reported.
84 // Loop can finish when another thread calls wrapper_mutex_unlock.
85 // coverity[loop_condition]
Gong Kefdb31922022-06-17 17:11:16 +080086 while (lock->locked) {
87 pthread_cond_wait(&lock->cond, &lock->lock);
88 }
89 lock->locked = 1;
90 pthread_mutex_unlock(&lock->lock);
91
92 return 0;
93}
94
95static int
96wrapper_mutex_unlock (DVR_WrapperMutex_t *lock)
97{
98 pthread_mutex_lock(&lock->lock);
99 lock->locked = 0;
100 pthread_mutex_unlock(&lock->lock);
101 pthread_cond_signal(&lock->cond);
102
103 return 0;
104}
105
106static int
107wrapper_mutex_timedlock (DVR_WrapperMutex_t *lock, struct timespec *tv)
108{
109 int r = 0;
110
111 pthread_mutex_lock(&lock->lock);
112 if (lock->locked) {
Zhiqiang Han61ceb3a2022-07-04 17:03:52 +0800113 //DVR_WRAPPER_DEBUG("Enter cond_timedwait");
Gong Kefdb31922022-06-17 17:11:16 +0800114 r = pthread_cond_timedwait(&lock->cond, &lock->lock, tv);
Zhiqiang Han61ceb3a2022-07-04 17:03:52 +0800115 //DVR_WRAPPER_DEBUG("Leave cond_timedwait");
Gong Kefdb31922022-06-17 17:11:16 +0800116 }
117 if (r == 0) {
118 if (!lock->locked) {
119 lock->locked = 1;
120 } else {
121 r = ETIMEDOUT;
122 }
123 }
124 pthread_mutex_unlock(&lock->lock);
125
126 return r;
127}
128
129#define WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(expr, lock)\
130 do {\
131 if (!(expr)) {\
132 DVR_INFO("%s-%d failed", __func__, __LINE__);\
133 wrapper_mutex_unlock(lock);\
134 return DVR_FAILURE;\
135 }\
136 } while (0);
137
138
139typedef struct {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800140 /*make lock the 1st item in the structure*/
Gong Kefdb31922022-06-17 17:11:16 +0800141 DVR_WrapperMutex_t wrapper_lock;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800142
143 /*rec or play*/
144 int type;
145
146 /*valid if (sn != 0)*/
147 unsigned long sn;
148 unsigned long sn_linked;
149
150 struct list_head segments; /**<head-add list*/
151 uint64_t current_segment_id; /**<id of the current segment*/
152
153 union {
154 struct {
155 DVR_WrapperRecordOpenParams_t param_open;
156 DVR_RecordStartParams_t param_start;
157 DVR_RecordStartParams_t param_update;
158 DVR_RecordHandle_t recorder;
159 DVR_RecordEventFunction_t event_fn;
160 void *event_userdata;
161
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800162 /*total status = seg_status + status + obsolete*/
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800163 DVR_RecordStatus_t seg_status; /**<status of current segment*/
164 DVR_WrapperRecordStatus_t status; /**<status of remaining segments*/
165 uint64_t next_segment_id;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800166
167 DVR_WrapperInfo_t obsolete; /**<data obsolete due to the max limit*/
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800168 } record;
169
170 struct {
171 DVR_WrapperPlaybackOpenParams_t param_open;
172 DVR_PlaybackHandle_t player;
173 DVR_PlaybackEventFunction_t event_fn;
174 void *event_userdata;
175
176 /*total status = seg_status + status*/
177 DVR_PlaybackStatus_t seg_status;
178 DVR_WrapperPlaybackStatus_t status;
179 DVR_PlaybackPids_t pids_req;
180 DVR_PlaybackEvent_t last_event;
Zhiqiang Han3eb75f92020-04-08 10:07:55 +0800181 float speed;
hualing chenb5cd42e2020-04-15 17:03:34 +0800182 DVR_Bool_t reach_end;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800183
184 DVR_WrapperInfo_t obsolete;
hualing chen56c0a162022-01-27 17:01:50 +0800185 DVR_Bool_t tf_full;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800186 } playback;
187 };
188} DVR_WrapperCtx_t;
189
190typedef struct {
191 struct list_head head;
192 unsigned long sn;
193
194 /* rec or playback */
195 int type;
196
197 union {
198 struct {
199 DVR_RecordEvent_t event;
200 DVR_RecordStatus_t status;
201 } record;
202 struct {
203 DVR_PlaybackEvent_t event;
204 DVR_Play_Notify_t status;
205 } playback;
206 };
207} DVR_WrapperEventCtx_t;
208
209typedef struct {
210 pthread_mutex_t lock;
211 char *name;
212 int running;
213 pthread_cond_t cond;
214 pthread_t thread;
215 int type;
216} DVR_WrapperThreadCtx_t;
217
218typedef struct {
219 struct list_head head;
220
221 DVR_RecordSegmentInfo_t seg_info;
222 DVR_PlaybackSegmentInfo_t playback_info;
223} DVR_WrapperPlaybackSegmentInfo_t;
224
225typedef struct {
226 struct list_head head;
227
228 DVR_RecordSegmentInfo_t info;
229} DVR_WrapperRecordSegmentInfo_t;
230
231/* serial num generater */
232static unsigned long sn = 1;
233static pthread_mutex_t sn_lock = PTHREAD_MUTEX_INITIALIZER;
234
235static inline unsigned long get_sn()
236{
hualing chenab0d1262021-09-26 15:22:50 +0800237 unsigned long no = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800238
239 pthread_mutex_lock(&sn_lock);
240 no = sn++;
241 if (!no)
242 no = sn++;
243 pthread_mutex_unlock(&sn_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800244 return no;
245}
246
247/* entity ctx */
248#define DVR_WRAPPER_MAX 10
249
250static DVR_WrapperCtx_t record_list[DVR_WRAPPER_MAX] =
251{
252 [0 ... (DVR_WRAPPER_MAX - 1)] =
253 {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800254 .type = W_REC,
255 }
256};
257
258static DVR_WrapperCtx_t playback_list[DVR_WRAPPER_MAX] =
259{
260 [0 ... (DVR_WRAPPER_MAX - 1)] =
261 {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800262 .type = W_PLAYBACK,
263 }
264};
265
266/* events lists */
267static struct list_head record_evt_list = LIST_HEAD_INIT(record_evt_list);
268static struct list_head playback_evt_list = LIST_HEAD_INIT(playback_evt_list);
269
270static pthread_mutex_t record_evt_list_lock = PTHREAD_MUTEX_INITIALIZER;
271static pthread_mutex_t playback_evt_list_lock = PTHREAD_MUTEX_INITIALIZER;
272
273static DVR_WrapperThreadCtx_t wrapper_thread[2] =
274{
275 [0] =
276 {
277 .lock = PTHREAD_MUTEX_INITIALIZER,
278 .running = 0,
279 .name = "record",
280 .type = W_REC,
281 },
282 [1] =
283 {
284 .lock = PTHREAD_MUTEX_INITIALIZER,
285 .running = 0,
286 .name = "playback",
287 .type = W_PLAYBACK,
288 },
289};
290
291/*now only support one timeshift now*/
292static unsigned long sn_timeshift_record;
293static unsigned long sn_timeshift_playback;
294
295static void *wrapper_task(void *arg);
296static inline int process_handleEvents(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx);
297
298static DVR_Result_t wrapper_record_event_handler(DVR_RecordEvent_t event, void *params, void *userdata);
299static DVR_Result_t wrapper_playback_event_handler(DVR_PlaybackEvent_t event, void *params, void *userdata);
300
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800301static int process_generateRecordStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordStatus_t *status);
302static int process_generatePlaybackStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperPlaybackStatus_t *status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800303
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800304static int get_timespec_timeout(int timeout, struct timespec *ts)
305{
306 struct timespec ots;
307 int left, diff;
308
309 clock_gettime(CLOCK_MONOTONIC, &ots);
310
311 ts->tv_sec = ots.tv_sec + timeout / 1000;
312 ts->tv_nsec = ots.tv_nsec;
313
314 left = timeout % 1000;
315 left *= 1000000;
316 diff = 1000000000 - ots.tv_nsec;
317
318 if (diff <= left) {
319 ts->tv_sec++;
320 ts->tv_nsec = left-diff;
321 } else {
322 ts->tv_nsec += left;
323 }
324
325 return 0;
326}
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800327
328static DVR_WrapperEventCtx_t *ctx_getEvent(struct list_head *list, pthread_mutex_t *list_lock)
329{
Wentao MA270dc0f2022-08-23 13:17:26 +0800330 DVR_WrapperEventCtx_t *p_evt;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800331
332 pthread_mutex_lock(list_lock);
333 if (list_empty(list))
Wentao MA270dc0f2022-08-23 13:17:26 +0800334 p_evt = NULL;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800335 else {
Wentao MA270dc0f2022-08-23 13:17:26 +0800336 p_evt = list_first_entry(list, DVR_WrapperEventCtx_t, head);
337 list_del(&p_evt->head);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800338 }
339 pthread_mutex_unlock(list_lock);
340
Wentao MA270dc0f2022-08-23 13:17:26 +0800341 return p_evt;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800342}
343
344static inline DVR_WrapperEventCtx_t *ctx_getRecordEvent()
345{
346 return ctx_getEvent(&record_evt_list, &record_evt_list_lock);
347}
348
349static inline DVR_WrapperEventCtx_t *ctx_getPlaybackEvent()
350{
351 return ctx_getEvent(&playback_evt_list, &playback_evt_list_lock);
352}
353
354static int ctx_addEvent(struct list_head *list, pthread_mutex_t *lock, DVR_WrapperEventCtx_t *evt)
355{
356 DVR_WrapperEventCtx_t *padd;
357 padd = (DVR_WrapperEventCtx_t *)calloc(1, sizeof(DVR_WrapperEventCtx_t));
358 DVR_RETURN_IF_FALSE(padd);
359
360 *padd = *evt;
361 pthread_mutex_lock(lock);
wentao.maa22bc852022-10-13 12:18:06 +0800362 list_add_tail(padd, list);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800363 pthread_mutex_unlock(lock);
364 return DVR_SUCCESS;
365}
366
367static inline void ctx_freeEvent(DVR_WrapperEventCtx_t *evt)
368{
369 free(evt);
370}
371
372/*useless*/
373static void ctx_cleanOutdatedEvents(struct list_head *evt_list,
374 pthread_mutex_t *evt_list_lock,
375 DVR_WrapperCtx_t *list)
376{
Wentao MA270dc0f2022-08-23 13:17:26 +0800377 DVR_WrapperEventCtx_t *p_evt, *p_evt_tmp;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800378 unsigned long sns[DVR_WRAPPER_MAX];
379 int cnt = 0;
380 int i;
381 int found = 0;
382
383 /*copy all valid sns*/
384 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
385 sns[cnt] = list[i].sn;
386 if (!sns[cnt])
387 cnt++;
388 }
389
390 /*free evts that not belong to any valid sns*/
391 pthread_mutex_lock(evt_list_lock);
Wentao MA270dc0f2022-08-23 13:17:26 +0800392 list_for_each_entry_safe(p_evt, p_evt_tmp, evt_list, head) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800393 for (i = 0; i < cnt; i++) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800394 if (p_evt->sn == sns[i]) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800395 found = 1;
396 break;
397 }
398 }
399 if (!found) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800400 list_del(&p_evt->head);
401 ctx_freeEvent(p_evt);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800402 }
403 }
404 pthread_mutex_unlock(evt_list_lock);
405}
406
407static inline void ctx_cleanOutdatedRecordEvents()
408{
409 ctx_cleanOutdatedEvents(&record_evt_list, &record_evt_list_lock, record_list);
410}
411
412static inline void ctx_cleanOutdatedPlaybackEvents()
413{
414 ctx_cleanOutdatedEvents(&playback_evt_list, &playback_evt_list_lock, playback_list);
415}
416
hualing chenb9b358a2021-08-17 15:06:36 +0800417//check this play is recording file
418//return 0 if not the recording
419//else return record id
420static inline int ctx_isPlay_recording(char *play_location)
421{
422 int i;
423 DVR_WrapperCtx_t *cnt;
424
425 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
426 cnt = &record_list[i];
Wentao MA96f68962022-06-15 19:45:35 +0800427 //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 +0800428 if (!strcmp(cnt->record.param_open.location, play_location)) {
Wentao MA96f68962022-06-15 19:45:35 +0800429 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 +0800430 return cnt->sn;
431 }
432 }
Wentao MA270dc0f2022-08-23 13:17:26 +0800433 DVR_WRAPPER_INFO(" not found any play is in recording [%d]", DVR_WRAPPER_MAX);
hualing chenb9b358a2021-08-17 15:06:36 +0800434 return 0;
435}
Wentao MA804bab12022-11-29 10:01:26 +0800436
437// Check if the given record is being played.
438// Return 0 if it is not being played, otherwise return its playback id.
hualing chenb9b358a2021-08-17 15:06:36 +0800439static inline int ctx_isRecord_playing(char *rec_location)
440{
441 int i;
442 DVR_WrapperCtx_t *cnt;
443 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
444 cnt = &playback_list[i];
Wentao MA96f68962022-06-15 19:45:35 +0800445 //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 +0800446 if (!strcmp(cnt->playback.param_open.location, rec_location)) {
Wentao MA804bab12022-11-29 10:01:26 +0800447 DVR_WRAPPER_DEBUG("[%d]sn[%d]P[%s]R[%s] ..found.",
448 i, cnt->sn, cnt->playback.param_open.location, rec_location);
hualing chenb9b358a2021-08-17 15:06:36 +0800449 return cnt->sn;
450 }
451 }
hualing chenb9b358a2021-08-17 15:06:36 +0800452 return 0;
453}
454
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800455static inline DVR_WrapperCtx_t *ctx_get(unsigned long sn, DVR_WrapperCtx_t *list)
456{
457 int i;
458 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
Gong Kefdb31922022-06-17 17:11:16 +0800459 if (list[i].sn == sn) {
460 wrapper_mutex_init(&list[i].wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800461 return &list[i];
Gong Kefdb31922022-06-17 17:11:16 +0800462 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800463 }
464 return NULL;
465}
466
467static inline void ctx_reset(DVR_WrapperCtx_t *ctx)
468{
469 memset((char *)ctx + offsetof(DVR_WrapperCtx_t, sn),
470 0,
471 sizeof(DVR_WrapperCtx_t) - offsetof(DVR_WrapperCtx_t, sn));
472}
473
474static inline int ctx_valid(DVR_WrapperCtx_t *ctx)
475{
476 return (ctx->sn != 0);
477}
478
479static inline DVR_WrapperCtx_t *ctx_getRecord(unsigned long sn)
480{
481 return ctx_get(sn, record_list);
482}
483
484static inline DVR_WrapperCtx_t *ctx_getPlayback(unsigned long sn)
485{
486 return ctx_get(sn, playback_list);
487}
488
489static int wrapper_requestThread(DVR_WrapperThreadCtx_t *ctx, void *(thread_fn)(void *))
490{
491 pthread_mutex_lock(&ctx->lock);
492 if (ctx->running == 0) {
wentao.maa210e5e2022-10-12 16:10:03 +0800493 pthread_condattr_t attr = {0};
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800494 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
495 pthread_cond_init(&ctx->cond, &attr);
496 pthread_condattr_destroy(&attr);
Wentao MA96f68962022-06-15 19:45:35 +0800497 DVR_WRAPPER_INFO("start wrapper thread(%s) ...\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800498 pthread_create(&ctx->thread, NULL, thread_fn, ctx);
Wentao MA96f68962022-06-15 19:45:35 +0800499 DVR_WRAPPER_INFO("wrapper thread(%s) started\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800500 }
501 ctx->running++;
502 pthread_mutex_unlock(&ctx->lock);
503 return 0;
504}
505
506static int wrapper_releaseThread(DVR_WrapperThreadCtx_t *ctx)
507{
508 pthread_mutex_lock(&ctx->lock);
509 ctx->running--;
510 if (!ctx->running) {
511 pthread_cond_broadcast(&ctx->cond);
512 pthread_mutex_unlock(&ctx->lock);
513
Wentao MA96f68962022-06-15 19:45:35 +0800514 DVR_WRAPPER_INFO("stop wrapper thread(%s) ...\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800515 pthread_join(ctx->thread, NULL);
Wentao MA96f68962022-06-15 19:45:35 +0800516 DVR_WRAPPER_INFO("wrapper thread(%s) stopped\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800517
518 pthread_mutex_lock(&ctx->lock);
519 if (!ctx->running) /*protect*/
520 pthread_cond_destroy(&ctx->cond);
521 }
522 pthread_mutex_unlock(&ctx->lock);
523 return 0;
524}
525
526#define WRAPPER_THREAD_RECORD (&wrapper_thread[0])
527#define WRAPPER_THREAD_PLAYBACK (&wrapper_thread[1])
528
529static inline int wrapper_requestThreadFor(DVR_WrapperCtx_t *ctx)
530{
531 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC)?
532 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
533 return wrapper_requestThread(thread_ctx, wrapper_task);
534}
535
536static inline int wrapper_releaseThreadFor(DVR_WrapperCtx_t *ctx)
537{
538 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC)?
539 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
540 return wrapper_releaseThread(thread_ctx);
541}
542
543static inline int wrapper_releaseThreadForType(int type)
544{
545 DVR_WrapperThreadCtx_t *thread_ctx = (type == W_REC)?
546 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
547 return wrapper_releaseThread(thread_ctx);
548}
549
550static inline void wrapper_threadSignal(DVR_WrapperThreadCtx_t *thread_ctx)
551{
552 pthread_cond_signal(&thread_ctx->cond);
553}
554
555static inline int wrapper_threadWait(DVR_WrapperThreadCtx_t *thread_ctx)
556{
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800557 struct timespec rt;
558 get_timespec_timeout(200, &rt);
559 pthread_cond_timedwait(&thread_ctx->cond, &thread_ctx->lock, &rt);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800560 return 0;
561}
562
563static inline void wrapper_threadSignalForType(int type)
564{
565 DVR_WrapperThreadCtx_t *thread_ctx = (type == W_REC) ?
566 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
567 wrapper_threadSignal(thread_ctx);
568}
569
570static inline void wrapper_threadSignalFor(DVR_WrapperCtx_t *ctx)
571{
572 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC) ?
573 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
574 wrapper_threadSignal(thread_ctx);
575}
576
577static inline int wrapper_threadWaitFor(DVR_WrapperCtx_t *ctx)
578{
579 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC) ?
580 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
581 wrapper_threadWait(thread_ctx);
582 return 0;
583}
584
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800585/*return condition, locked if condition == true*/
Gong Kefdb31922022-06-17 17:11:16 +0800586static int wrapper_mutex_lock_if(DVR_WrapperMutex_t *lock, int *condition)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800587{
588 int r2;
589 do {
590 struct timespec rt2;
Gong Kefdb31922022-06-17 17:11:16 +0800591 get_timespec_timeout(10, &rt2);
592 r2 = wrapper_mutex_timedlock(lock, &rt2);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800593 } while (*condition && (r2 == ETIMEDOUT));
594
595 if (!(*condition) && (r2 == 0))
Gong Kefdb31922022-06-17 17:11:16 +0800596 wrapper_mutex_unlock(lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800597
598 return *condition;
599}
600
601static void *wrapper_task(void *arg)
602{
Wentao MA270dc0f2022-08-23 13:17:26 +0800603 DVR_WrapperThreadCtx_t *thread_ctx = (DVR_WrapperThreadCtx_t *)arg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800604 DVR_WrapperEventCtx_t *evt;
605
Wentao MA270dc0f2022-08-23 13:17:26 +0800606 pthread_mutex_lock(&thread_ctx->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800607
Wentao MA270dc0f2022-08-23 13:17:26 +0800608 while (thread_ctx->running) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800609 {
610 int ret;
hualing chene3797f02021-01-13 14:53:28 +0800611
Wentao MA270dc0f2022-08-23 13:17:26 +0800612 evt = (thread_ctx->type == W_REC)? ctx_getRecordEvent() : ctx_getPlaybackEvent();
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800613 if (!evt)
Wentao MA270dc0f2022-08-23 13:17:26 +0800614 ret = wrapper_threadWait(thread_ctx);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800615 }
616
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800617 while (evt) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800618 DVR_WrapperCtx_t *ctx = (evt->type == W_REC)?
619 ctx_getRecord(evt->sn) : ctx_getPlayback(evt->sn);
hualing chenbc0aec92021-03-18 14:52:40 +0800620 if (ctx == NULL) {
Wentao MA804bab12022-11-29 10:01:26 +0800621 DVR_WRAPPER_ERROR("Wrapper context is NULL");
hualing chenbc0aec92021-03-18 14:52:40 +0800622 goto processed;
623 }
Wentao MA804bab12022-11-29 10:01:26 +0800624 DVR_WRAPPER_DEBUG("start name(%s) sn(%d) running(%d) type(%d)\n", thread_ctx->name, (int)ctx->sn, thread_ctx->running, thread_ctx->type);
Wentao MA270dc0f2022-08-23 13:17:26 +0800625 if (thread_ctx->running) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800626 /*
627 continue not break,
628 make all events consumed, or mem leak
629 */
Wentao MA270dc0f2022-08-23 13:17:26 +0800630 if (!wrapper_mutex_lock_if(&ctx->wrapper_lock, &thread_ctx->running))
Zhiqiang Hanef61c0a2020-04-13 15:49:24 +0800631 goto processed;
632
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800633 if (ctx_valid(ctx)) {
634 /*double check after lock*/
Zhiqiang Han3b9c9082021-11-10 10:41:09 +0800635 if (evt->sn == ctx->sn) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800636 pthread_mutex_unlock(&thread_ctx->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800637 process_handleEvents(evt, ctx);
Wentao MA270dc0f2022-08-23 13:17:26 +0800638 pthread_mutex_lock(&thread_ctx->lock);
Zhiqiang Han3b9c9082021-11-10 10:41:09 +0800639 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800640 }
Gong Kefdb31922022-06-17 17:11:16 +0800641 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800642 }
643
Zhiqiang Hanef61c0a2020-04-13 15:49:24 +0800644processed:
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800645 ctx_freeEvent(evt);
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800646
Wentao MA270dc0f2022-08-23 13:17:26 +0800647 evt = (thread_ctx->type == W_REC)? ctx_getRecordEvent() : ctx_getPlaybackEvent();
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800648 }
649 }
650
Wentao MA270dc0f2022-08-23 13:17:26 +0800651 pthread_mutex_unlock(&thread_ctx->lock);
Wentao MA804bab12022-11-29 10:01:26 +0800652 DVR_WRAPPER_DEBUG("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.mafd5283f2022-10-14 09:51:13 +0800732 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +0800733 // prefetch() here incurring self_assign is used to avoid some compiling
734 // warnings.
735 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +0800736 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
737 if (p_seg->seg_info.id == seg_info->id) {
738 _updatePlaybackSegment(p_seg, seg_info, update_flags, ctx);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800739 break;
740 }
741 }
742 }
743
744 /*need to notify the dvr_playback*/
hualing chenb9b358a2021-08-17 15:06:36 +0800745 if ((ctx->playback.param_open.is_timeshift/*should must be timeshift*/
746 || ctx_isPlay_recording(ctx->playback.param_open.location))
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800747 && ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_END
748 && ctx->playback.seg_status.state == DVR_PLAYBACK_STATE_PAUSE) {
749 if (
750 /*there's $TIMESHIFT_DATA_DURATION_TO_RESUME more of data in the current segment playing*/
751 (ctx->playback.seg_status.segment_id == seg_info->id
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.mafd5283f2022-10-14 09:51:13 +0800802 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +0800803 // 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;
Wentao MA2394fa82022-06-10 14:46:47 +08001106
Wentao MA2394fa82022-06-10 14:46:47 +08001107 uint64_t new_segment_id = 0;
wentao.ma997da2f2022-11-14 16:31:59 +08001108
1109 {
1110 uint32_t segment_nb = 0;
1111 uint64_t *p_segment_ids = NULL;
1112 error = dvr_segment_get_list(params->location, &segment_nb, &p_segment_ids);
1113 if (error == DVR_SUCCESS && segment_nb>0) {
1114 // Tainted data issue originating from fgets seem false positive, so we
1115 // just suppress it here.
1116 // coverity[tainted_data]
1117 new_segment_id = p_segment_ids[segment_nb-1]+1;
1118 }
1119 if (p_segment_ids != NULL) {
1120 free(p_segment_ids);
1121 }
1122 DVR_WRAPPER_DEBUG("new_segment_id:%lld\n", new_segment_id);
Wentao MA2394fa82022-06-10 14:46:47 +08001123 }
Wentao MA2394fa82022-06-10 14:46:47 +08001124
1125 ctx->record.next_segment_id = new_segment_id;
1126 ctx->current_segment_id = new_segment_id;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001127 INIT_LIST_HEAD(&ctx->segments);
1128 ctx->sn = get_sn();
1129
1130 wrapper_requestThreadFor(ctx);
1131
hualing chen266b9502020-04-04 17:39:39 +08001132 memset(&open_param, 0, sizeof(DVR_RecordOpenParams_t));
Yahui Hance15e9c2020-12-08 18:08:32 +08001133 open_param.fend_dev_id = params->fend_dev_id;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001134 open_param.dmx_dev_id = params->dmx_dev_id;
1135 open_param.data_from_memory = 0;
1136 open_param.flags = params->flags;
Yahui Han15a00f12021-11-15 19:44:39 +08001137 if (params->flush_size) {
1138 open_param.notification_size = params->flush_size;
1139 } else {
1140 open_param.notification_size = 64*1024;
1141 }
hualing chen002e5b92022-02-23 17:51:21 +08001142 open_param.notification_time = 400;//ms
Zhiqiang Han31505452020-05-06 15:08:10 +08001143 open_param.flush_size = params->flush_size;
hualing chen03fd4942021-07-15 15:56:41 +08001144 open_param.ringbuf_size = params->ringbuf_size;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001145 open_param.event_fn = wrapper_record_event_handler;
1146 open_param.event_userdata = (void*)ctx->sn;
Yahui Han1fbf3292021-11-08 18:17:19 +08001147 if (params->keylen) {
1148 open_param.clearkey = params->clearkey;
1149 open_param.cleariv = params->cleariv;
1150 open_param.keylen = params->keylen;
1151 }
wentao.ma35a69d42022-03-10 18:08:40 +08001152 open_param.force_sysclock = params->force_sysclock;
Wentao MAeeffdb02022-06-27 16:34:35 +08001153 open_param.guarded_segment_size = params->segment_size/2*3;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001154
1155 error = dvr_record_open(&ctx->record.recorder, &open_param);
1156 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001157 DVR_WRAPPER_INFO("record(dmx:%d) open fail(error:%d).\n", params->dmx_dev_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001158 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001159 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001160 wrapper_releaseThreadForType(ctx->type);
1161 return DVR_FAILURE;
1162 }
1163 if (params->is_timeshift)
1164 sn_timeshift_record = ctx->sn;
1165
Wentao MA96f68962022-06-15 19:45:35 +08001166 DVR_WRAPPER_INFO("record(dmx:%d) openned ok(sn:%ld).\n", params->dmx_dev_id, ctx->sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001167
Yahui Han1fbf3292021-11-08 18:17:19 +08001168 if (params->crypto_fn) {
1169 error = dvr_record_set_encrypt_callback(ctx->record.recorder, params->crypto_fn, params->crypto_data);
1170 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001171 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 +08001172 }
hualing chen266b9502020-04-04 17:39:39 +08001173 }
1174
Gong Kefdb31922022-06-17 17:11:16 +08001175 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001176
1177 *rec = (DVR_WrapperRecord_t)ctx->sn;
1178 return DVR_SUCCESS;
1179}
1180
1181int dvr_wrapper_close_record (DVR_WrapperRecord_t rec)
1182{
1183 DVR_WrapperCtx_t *ctx;
1184 DVR_RecordSegmentInfo_t seg_info;
1185 int error;
1186
1187 DVR_RETURN_IF_FALSE(rec);
1188
1189 ctx = ctx_getRecord((unsigned long)rec);
1190 DVR_RETURN_IF_FALSE(ctx);
1191
Gong Kefdb31922022-06-17 17:11:16 +08001192 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001193 DVR_WRAPPER_INFO("close record(sn:%ld)\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001194 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001195
1196 memset(&seg_info, 0, sizeof(seg_info));
wentao.maa210e5e2022-10-12 16:10:03 +08001197 dvr_record_stop_segment(ctx->record.recorder, &seg_info);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001198
1199 error = dvr_record_close(ctx->record.recorder);
1200
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001201 if (ctx->record.param_open.is_timeshift)
1202 sn_timeshift_record = 0;
1203
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001204 ctx_freeSegments(ctx);
1205
Wentao MA96f68962022-06-15 19:45:35 +08001206 DVR_WRAPPER_INFO("record(sn:%ld) closed = (%d).\n", ctx->sn, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001207 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001208 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001209
1210 wrapper_releaseThreadForType(ctx->type);
1211
1212 return error;
1213}
1214
1215int dvr_wrapper_start_record (DVR_WrapperRecord_t rec, DVR_WrapperRecordStartParams_t *params)
1216{
1217 DVR_WrapperCtx_t *ctx;
1218 DVR_RecordStartParams_t *start_param;
1219 int i;
1220 int error;
1221
1222 DVR_RETURN_IF_FALSE(rec);
1223 DVR_RETURN_IF_FALSE(params);
1224
1225 ctx = ctx_getRecord((unsigned long)rec);
1226 DVR_RETURN_IF_FALSE(ctx);
1227
Gong Kefdb31922022-06-17 17:11:16 +08001228 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08001229 DVR_WRAPPER_INFO("libdvr_api, start_record (sn:%ld) location:%s, save:%d",
1230 ctx->sn, ctx->record.param_open.location, params->save_rec_file);
Gong Kefdb31922022-06-17 17:11:16 +08001231 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001232
1233 start_param = &ctx->record.param_start;
1234 memset(start_param, 0, sizeof(*start_param));
Wentao MAe88ad702022-09-02 10:35:00 +08001235 const int len = strlen(ctx->record.param_open.location);
1236 if (len >= DVR_MAX_LOCATION_SIZE || len <= 0) {
1237 DVR_WRAPPER_ERROR("Invalid record.param_open.location length %d",len);
1238 pthread_mutex_unlock(&ctx->wrapper_lock);
1239 return DVR_FAILURE;
1240 }
1241 strncpy(start_param->location, ctx->record.param_open.location, len+1);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001242 start_param->segment.segment_id = ctx->record.next_segment_id++;
1243 start_param->segment.nb_pids = params->pids_info.nb_pids;
1244 for (i = 0; i < params->pids_info.nb_pids; i++) {
1245 start_param->segment.pids[i] = params->pids_info.pids[i];
1246 start_param->segment.pid_action[i] = DVR_RECORD_PID_CREATE;
1247 }
hualing chena5f03222021-12-02 11:22:35 +08001248 if (params->save_rec_file == 0)//default is not save
1249 dvr_segment_del_by_location(start_param->location);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001250 {
1251 /*sync to update for further use*/
1252 DVR_RecordStartParams_t *update_param;
1253 update_param = &ctx->record.param_update;
1254 memcpy(update_param, start_param, sizeof(*update_param));
1255 for (i = 0; i < update_param->segment.nb_pids; i++)
1256 update_param->segment.pid_action[i] = DVR_RECORD_PID_KEEP;
1257 }
1258
1259 error = dvr_record_start_segment(ctx->record.recorder, start_param);
1260 {
1261 DVR_RecordSegmentInfo_t new_seg_info =
1262 { .id = start_param->segment.segment_id, };
1263 wrapper_addRecordSegment(ctx, &new_seg_info);
1264 }
1265
Wentao MA96f68962022-06-15 19:45:35 +08001266 DVR_WRAPPER_INFO("record(sn:%ld) started = (%d)\n", ctx->sn, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001267
Gong Kefdb31922022-06-17 17:11:16 +08001268 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001269
1270 return error;
1271}
1272
1273int dvr_wrapper_stop_record (DVR_WrapperRecord_t rec)
1274{
1275 DVR_WrapperCtx_t *ctx;
1276 DVR_RecordSegmentInfo_t seg_info;
1277 int error;
1278
1279 DVR_RETURN_IF_FALSE(rec);
1280
1281 ctx = ctx_getRecord((unsigned long)rec);
1282 DVR_RETURN_IF_FALSE(ctx);
1283
Gong Kefdb31922022-06-17 17:11:16 +08001284 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08001285 DVR_WRAPPER_INFO("libdvr_api, stop_record (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001286 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001287
1288 memset(&seg_info, 0, sizeof(seg_info));
1289 error = dvr_record_stop_segment(ctx->record.recorder, &seg_info);
1290 wrapper_updateRecordSegment(ctx, &seg_info, U_ALL);
1291
Wentao MA96f68962022-06-15 19:45:35 +08001292 DVR_WRAPPER_INFO("record(sn:%ld) stopped = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001293 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001294
1295 return error;
1296}
1297
hualing chen03fd4942021-07-15 15:56:41 +08001298int dvr_wrapper_pause_record (DVR_WrapperRecord_t rec)
1299{
1300 DVR_WrapperCtx_t *ctx;
1301 int error;
1302
1303 DVR_RETURN_IF_FALSE(rec);
1304
1305 ctx = ctx_getRecord((unsigned long)rec);
1306 DVR_RETURN_IF_FALSE(ctx);
1307
Gong Kefdb31922022-06-17 17:11:16 +08001308 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08001309 DVR_WRAPPER_INFO("libdvr_api, pause_record (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001310 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001311
1312 error = dvr_record_pause(ctx->record.recorder);
1313
Wentao MA96f68962022-06-15 19:45:35 +08001314 DVR_WRAPPER_INFO("record(sn:%ld) pauseed = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001315 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001316
1317 return error;
1318}
1319
1320int dvr_wrapper_resume_record (DVR_WrapperRecord_t rec)
1321{
1322 DVR_WrapperCtx_t *ctx;
1323 int error;
1324
1325 DVR_RETURN_IF_FALSE(rec);
1326
1327 ctx = ctx_getRecord((unsigned long)rec);
1328 DVR_RETURN_IF_FALSE(ctx);
1329
Gong Kefdb31922022-06-17 17:11:16 +08001330 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08001331 DVR_WRAPPER_INFO("libdvr_api, resume_record (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001332 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001333
1334 error = dvr_record_resume(ctx->record.recorder);
1335
Wentao MA96f68962022-06-15 19:45:35 +08001336 DVR_WRAPPER_INFO("record(sn:%ld) resumed = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001337 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001338
1339 return error;
1340}
1341
Wentao MAcdea4762022-04-26 13:28:56 +08001342/* Return true if arr1 contains all elements in arr2 */
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001343static DVR_Bool_t pids_test_include(
1344 DVR_StreamPid_t* arr1, DVR_RecordPidAction_t *act1, int size1,
1345 DVR_StreamPid_t* arr2, DVR_RecordPidAction_t *act2, int size2)
wentao.maa69578c2022-04-07 09:27:39 +08001346{
Wentao MAcdea4762022-04-26 13:28:56 +08001347 DVR_Bool_t ret = DVR_TRUE;
1348 for (int i=0;i<size2;i++)
1349 { // iterate all elements in arr2 to check if they exist in arr1
1350 DVR_Bool_t found=DVR_FALSE;
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001351
1352 if (act2[i] == DVR_RECORD_PID_CLOSE)
1353 continue;
1354
Wentao MAcdea4762022-04-26 13:28:56 +08001355 for (int j=0;j<size1;j++)
wentao.maa69578c2022-04-07 09:27:39 +08001356 {
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001357 if (act1[j] != DVR_RECORD_PID_CLOSE
1358 && arr2[i].pid == arr1[j].pid)
wentao.maa69578c2022-04-07 09:27:39 +08001359 {
1360 found=DVR_TRUE;
1361 break;
1362 }
1363 }
1364 if (found == DVR_FALSE)
1365 {
Wentao MAcdea4762022-04-26 13:28:56 +08001366 ret=DVR_FALSE;
wentao.maa69578c2022-04-07 09:27:39 +08001367 break;
1368 }
1369 }
Wentao MAcdea4762022-04-26 13:28:56 +08001370 return ret;
1371}
1372
1373static DVR_Bool_t pids_equal(const DVR_RecordSegmentStartParams_t* p1,
1374 const DVR_WrapperUpdatePidsParams_t* p2)
1375{
1376 int i=0;
1377 char buf[128]={0};
1378 int cnt=0;
1379 int chars=0;
1380
1381 DVR_RETURN_IF_FALSE(p1 != NULL && p2 != NULL);
1382 DVR_RETURN_IF_FALSE(p1->nb_pids>0 && p2->nb_pids>0);
1383
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001384 DVR_Bool_t cond1 = pids_test_include(p1->pids,p1->pid_action,p1->nb_pids,
1385 p2->pids,p2->pid_action,p2->nb_pids);
1386 DVR_Bool_t cond2 = pids_test_include(p2->pids,p2->pid_action,p2->nb_pids,
1387 p1->pids,p1->pid_action,p1->nb_pids);
Wentao MAcdea4762022-04-26 13:28:56 +08001388 DVR_Bool_t is_equal = (cond1 && cond2);
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001389 int removed;
Wentao MAcdea4762022-04-26 13:28:56 +08001390
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001391 removed = 0;
Wentao MAcdea4762022-04-26 13:28:56 +08001392 for (i=0;i<p1->nb_pids;i++)
1393 {
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001394 if (p1->pid_action[i] == DVR_RECORD_PID_CLOSE) {
1395 removed++;
1396 continue;
1397 }
Wentao MAcdea4762022-04-26 13:28:56 +08001398 chars = snprintf(buf+cnt,sizeof(buf)-cnt,"0x%hx,",p1->pids[i].pid);
1399 if (chars<0)
1400 {
1401 break;
1402 }
1403 cnt += chars;
1404 }
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001405 DVR_INFO("%s nb_pids1:%d, pids1: %s",__func__,p1->nb_pids-removed,buf);
Wentao MAcdea4762022-04-26 13:28:56 +08001406 memset(buf,0,sizeof(buf));
1407
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001408 removed = 0;
Wentao MAcdea4762022-04-26 13:28:56 +08001409 for (i=0,cnt=0;i<p2->nb_pids;i++)
1410 {
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001411 if (p2->pid_action[i] == DVR_RECORD_PID_CLOSE) {
1412 removed++;
1413 continue;
1414 }
Wentao MAcdea4762022-04-26 13:28:56 +08001415 chars = snprintf(buf+cnt,sizeof(buf)-cnt,"0x%hx,",p2->pids[i].pid);
1416 if (chars<0)
1417 {
1418 break;
1419 }
1420 cnt += chars;
1421 }
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001422 DVR_INFO("%s nb_pids2:%d, pids2: %s",__func__,p2->nb_pids-removed,buf);
Wentao MA96f68962022-06-15 19:45:35 +08001423 DVR_INFO("%s is_equal:%d",__func__,is_equal);
wentao.maa69578c2022-04-07 09:27:39 +08001424 return is_equal;
1425}
1426
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001427int dvr_wrapper_update_record_pids (DVR_WrapperRecord_t rec, DVR_WrapperUpdatePidsParams_t *params)
1428{
1429 DVR_WrapperCtx_t *ctx;
1430 DVR_RecordStartParams_t *start_param;
wentao.maa69578c2022-04-07 09:27:39 +08001431 DVR_RecordSegmentInfo_t seg_info;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001432 int i;
1433 int error;
1434
1435 DVR_RETURN_IF_FALSE(rec);
1436 DVR_RETURN_IF_FALSE(params);
1437
1438 ctx = ctx_getRecord((unsigned long)rec);
1439 DVR_RETURN_IF_FALSE(ctx);
1440
Gong Kefdb31922022-06-17 17:11:16 +08001441 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08001442 DVR_WRAPPER_INFO("libdvr_api, update_record (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001443 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001444
1445 start_param = &ctx->record.param_update;
wentao.maa69578c2022-04-07 09:27:39 +08001446 if (pids_equal(&(start_param->segment),params))
1447 {
Gong Kefdb31922022-06-17 17:11:16 +08001448 wrapper_mutex_unlock(&ctx->wrapper_lock);
wentao.maa69578c2022-04-07 09:27:39 +08001449 return DVR_TRUE;
1450 }
1451
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001452 memset(start_param, 0, sizeof(*start_param));
Wentao MAe88ad702022-09-02 10:35:00 +08001453 const int len = strlen(ctx->record.param_open.location);
1454 if (len >= DVR_MAX_LOCATION_SIZE || len <= 0) {
1455 DVR_WRAPPER_ERROR("Invalid record.param_open.location length %d",len);
1456 pthread_mutex_unlock(&ctx->wrapper_lock);
1457 return DVR_FAILURE;
1458 }
1459 strncpy(start_param->location, ctx->record.param_open.location, len+1);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001460 start_param->segment.segment_id = ctx->record.next_segment_id++;
1461 start_param->segment.nb_pids = params->nb_pids;
1462 for (i = 0; i < params->nb_pids; i++) {
1463 start_param->segment.pids[i] = params->pids[i];
1464 start_param->segment.pid_action[i] = params->pid_action[i];
1465 }
1466 error = dvr_record_next_segment(ctx->record.recorder, start_param, &seg_info);
1467 {
1468 DVR_RecordSegmentInfo_t new_seg_info =
1469 { .id = start_param->segment.segment_id, };
1470 wrapper_updateRecordSegment(ctx, &seg_info, U_PIDS);
1471 wrapper_addRecordSegment(ctx, &new_seg_info);
1472 }
1473
Wentao MA96f68962022-06-15 19:45:35 +08001474 DVR_WRAPPER_INFO("record(sn:%ld) updated = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001475 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001476
1477 return error;
1478}
1479
1480int dvr_wrapper_get_record_status(DVR_WrapperRecord_t rec, DVR_WrapperRecordStatus_t *status)
1481{
1482 DVR_WrapperCtx_t *ctx;
1483 DVR_WrapperRecordStatus_t s;
1484 int error;
1485
1486 DVR_RETURN_IF_FALSE(rec);
1487 DVR_RETURN_IF_FALSE(status);
1488
1489 ctx = ctx_getRecord((unsigned long)rec);
1490 DVR_RETURN_IF_FALSE(ctx);
1491
Gong Kefdb31922022-06-17 17:11:16 +08001492 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001493
Wentao MA804bab12022-11-29 10:01:26 +08001494 DVR_WRAPPER_INFO("libdvr_api, get_record_status (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001495 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001496
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001497 error = process_generateRecordStatus(ctx, &s);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001498
Wentao MA96f68962022-06-15 19:45:35 +08001499 DVR_WRAPPER_INFO("record(sn:%ld) state/time/size/pkts(%d/%ld/%lld/%u) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001500 ctx->sn,
1501 s.state,
1502 s.info.time,
1503 s.info.size,
1504 s.info.pkts,
1505 error);
1506
1507 *status = s;
1508
Gong Kefdb31922022-06-17 17:11:16 +08001509 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001510
1511 return error;
1512}
1513
hualing chen4fe3bee2020-10-23 13:58:52 +08001514int dvr_wrapper_record_is_secure_mode(DVR_WrapperRecord_t rec)
1515{
1516 DVR_WrapperCtx_t *ctx;
1517 int error;
1518
1519 DVR_RETURN_IF_FALSE(rec);
1520
1521 ctx = ctx_getRecord((unsigned long)rec);
1522 DVR_RETURN_IF_FALSE(ctx);
1523
Gong Kefdb31922022-06-17 17:11:16 +08001524 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen4fe3bee2020-10-23 13:58:52 +08001525 error = dvr_record_is_secure_mode(ctx->record.recorder);
Gong Kefdb31922022-06-17 17:11:16 +08001526 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen4fe3bee2020-10-23 13:58:52 +08001527 return error;
1528}
1529
hualing chen266b9502020-04-04 17:39:39 +08001530int dvr_wrapper_set_record_secure_buffer (DVR_WrapperRecord_t rec, uint8_t *p_secure_buf, uint32_t len)
1531{
1532 DVR_WrapperCtx_t *ctx;
1533 int error;
1534
1535 DVR_RETURN_IF_FALSE(rec);
1536 DVR_RETURN_IF_FALSE(p_secure_buf);
1537
1538 ctx = ctx_getRecord((unsigned long)rec);
1539 DVR_RETURN_IF_FALSE(ctx);
1540
Gong Kefdb31922022-06-17 17:11:16 +08001541 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001542 error = dvr_record_set_secure_buffer(ctx->record.recorder, p_secure_buf, len);
Gong Kefdb31922022-06-17 17:11:16 +08001543 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001544 return error;
1545}
1546
1547int dvr_wrapper_set_record_decrypt_callback (DVR_WrapperRecord_t rec, DVR_CryptoFunction_t func, void *userdata)
1548{
1549 DVR_WrapperCtx_t *ctx;
1550 int error;
1551
1552 DVR_RETURN_IF_FALSE(rec);
1553 DVR_RETURN_IF_FALSE(func);
1554
1555 ctx = ctx_getRecord((unsigned long)rec);
1556 DVR_RETURN_IF_FALSE(ctx);
1557
Gong Kefdb31922022-06-17 17:11:16 +08001558 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001559 error = dvr_record_set_encrypt_callback(ctx->record.recorder, func, userdata);
Gong Kefdb31922022-06-17 17:11:16 +08001560 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001561 return error;
1562}
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001563
1564
1565int dvr_wrapper_open_playback (DVR_WrapperPlayback_t *playback, DVR_WrapperPlaybackOpenParams_t *params)
1566{
1567 DVR_WrapperCtx_t *ctx;
1568 DVR_PlaybackOpenParams_t open_param;
1569 int error;
1570
1571 DVR_RETURN_IF_FALSE(playback);
1572 DVR_RETURN_IF_FALSE(params);
1573 DVR_RETURN_IF_FALSE(params->playback_handle);
1574
1575 /*get a free ctx*/
1576 ctx = ctx_getPlayback(0);
1577 DVR_RETURN_IF_FALSE(ctx);
1578
Gong Kefdb31922022-06-17 17:11:16 +08001579 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001580
Wentao MA804bab12022-11-29 10:01:26 +08001581 DVR_WRAPPER_INFO("libdvr_api, open_playback (dmx:%d) ..vendor[%d]params->block_size[%d].",
1582 params->dmx_dev_id, params->vendor, params->block_size);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001583
1584 ctx_reset(ctx);
1585
1586 ctx->playback.param_open = *params;
1587 ctx->playback.event_fn = params->event_fn;
1588 ctx->playback.event_userdata = params->event_userdata;
1589 ctx->current_segment_id = 0;
1590 INIT_LIST_HEAD(&ctx->segments);
1591 ctx->sn = get_sn();
1592
1593 wrapper_requestThreadFor(ctx);
1594
hualing chen266b9502020-04-04 17:39:39 +08001595 memset(&open_param, 0, sizeof(DVR_PlaybackOpenParams_t));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001596 open_param.dmx_dev_id = params->dmx_dev_id;
1597 open_param.block_size = params->block_size;
1598 open_param.is_timeshift = params->is_timeshift;
1599 //open_param.notification_size = 10*1024; //not supported
1600 open_param.event_fn = wrapper_playback_event_handler;
1601 open_param.event_userdata = (void*)ctx->sn;
1602 /*open_param.has_pids = 0;*/
hualing chene3797f02021-01-13 14:53:28 +08001603 open_param.is_notify_time = params->is_notify_time;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001604 open_param.player_handle = (am_tsplayer_handle)params->playback_handle;
hualing chen90b3ae62021-03-30 10:49:28 +08001605 open_param.vendor = params->vendor;
1606
Yahui Han1fbf3292021-11-08 18:17:19 +08001607 if (params->keylen) {
1608 open_param.clearkey = params->clearkey;
1609 open_param.cleariv = params->cleariv;
1610 open_param.keylen = params->keylen;
1611 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001612
1613 error = dvr_playback_open(&ctx->playback.player, &open_param);
1614 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001615 DVR_WRAPPER_INFO("playback(dmx:%d) openned fail(error:%d).\n", params->dmx_dev_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001616 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001617 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001618 wrapper_releaseThreadForType(ctx->type);
1619 return DVR_FAILURE;
1620 }
1621 if (params->is_timeshift)
1622 sn_timeshift_playback = ctx->sn;
1623
Wentao MA270dc0f2022-08-23 13:17:26 +08001624 DVR_WRAPPER_INFO("playback(dmx:%d) openned ok(sn:%ld).\n", params->dmx_dev_id, ctx->sn);
hualing chen266b9502020-04-04 17:39:39 +08001625 error = dvr_playback_set_decrypt_callback(ctx->playback.player, params->crypto_fn, params->crypto_data);
1626 if (error) {
Wentao MA270dc0f2022-08-23 13:17:26 +08001627 DVR_WRAPPER_INFO("playback set decrypt callback fail(error:%d).\n", error);
hualing chen266b9502020-04-04 17:39:39 +08001628 }
Gong Kefdb31922022-06-17 17:11:16 +08001629 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001630
1631 *playback = (DVR_WrapperPlayback_t)ctx->sn;
1632 return DVR_SUCCESS;
1633}
1634
1635int dvr_wrapper_close_playback (DVR_WrapperPlayback_t playback)
1636{
1637 DVR_WrapperCtx_t *ctx;
1638 int error;
1639
1640 DVR_RETURN_IF_FALSE(playback);
1641
1642 ctx = ctx_getPlayback((unsigned long)playback);
1643 DVR_RETURN_IF_FALSE(ctx);
1644
Gong Kefdb31922022-06-17 17:11:16 +08001645 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08001646 DVR_WRAPPER_INFO("libdvr_api, close_playback (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001647 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001648
1649 if (ctx->playback.param_open.is_timeshift)
1650 sn_timeshift_playback = 0;
1651
1652 /*try stop first*/
wentao.maa210e5e2022-10-12 16:10:03 +08001653 dvr_playback_stop(ctx->playback.player, DVR_TRUE);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001654
1655 {
1656 /*remove all segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08001657 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001658
wentao.mafd5283f2022-10-14 09:51:13 +08001659 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08001660 // prefetch() here incurring self_assign is used to avoid some compiling
1661 // warnings.
1662 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08001663 list_for_each_entry(p_seg, &ctx->segments, head) {
1664 error = dvr_playback_remove_segment(ctx->playback.player, p_seg->playback_info.segment_id);
Wentao MA96f68962022-06-15 19:45:35 +08001665 DVR_WRAPPER_INFO("playback(sn:%ld) remove seg(%lld) (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08001666 ctx->sn, p_seg->playback_info.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001667 }
1668 ctx_freeSegments(ctx);
1669 }
1670
1671 error = dvr_playback_close(ctx->playback.player);
1672
Wentao MA96f68962022-06-15 19:45:35 +08001673 DVR_WRAPPER_INFO("playback(sn:%ld) closed.\n", ctx->sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001674 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001675 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001676
1677 wrapper_releaseThreadForType(ctx->type);
1678
1679 return error;
1680}
1681
1682int dvr_wrapper_start_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackFlag_t flags, DVR_PlaybackPids_t *p_pids)
1683{
1684 DVR_WrapperCtx_t *ctx;
Wentao MA9aa0aa02021-12-23 18:30:17 +08001685 int error=0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001686 uint64_t *p_segment_ids;
1687 uint32_t segment_nb;
1688 uint32_t i;
1689 DVR_RecordSegmentInfo_t seg_info_1st;
Wentao MA9aa0aa02021-12-23 18:30:17 +08001690 int got_1st_seg=0;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001691 DVR_WrapperCtx_t *ctx_record;/*for timeshift*/
hualing chenc110f952021-01-18 11:25:37 +08001692 DVR_Bool_t is_timeshift = DVR_FALSE;
Wentao MAcefc13c2022-10-26 15:47:24 +08001693 DVR_PlaybackSegmentFlag_t seg_flags = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001694
1695 DVR_RETURN_IF_FALSE(playback);
1696 DVR_RETURN_IF_FALSE(p_pids);
1697
hualing chenc110f952021-01-18 11:25:37 +08001698 ctx_record = NULL;
1699
1700 /*lock the recorder to avoid changing the recording segments*/
1701 ctx_record = ctx_getRecord(sn_timeshift_record);
1702
1703 if (ctx_record) {
Gong Kefdb31922022-06-17 17:11:16 +08001704 wrapper_mutex_lock(&ctx_record->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001705 if (!ctx_valid(ctx_record)
1706 || ctx_record->sn != sn_timeshift_record) {
Wentao MA96f68962022-06-15 19:45:35 +08001707 DVR_WRAPPER_INFO("timeshift, record is not for timeshifting, FATAL error found\n");
Gong Kefdb31922022-06-17 17:11:16 +08001708 wrapper_mutex_unlock(&ctx_record->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001709 is_timeshift = DVR_FALSE;
1710 } else {
1711 is_timeshift = DVR_TRUE;
1712 }
1713 }
1714
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001715 ctx = ctx_getPlayback((unsigned long)playback);
1716 DVR_RETURN_IF_FALSE(ctx);
1717
Gong Kefdb31922022-06-17 17:11:16 +08001718 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001719
Wentao MA804bab12022-11-29 10:01:26 +08001720 DVR_WRAPPER_INFO("libdvr_api, start_playback (sn:%ld) location:%s"
1721 " flags:0x%x v/a/ad/sub/pcr(%d:%d %d:%d %d:%d %d:%d %d)",
1722 ctx->sn,
1723 ctx->playback.param_open.location,
1724 flags,
1725 p_pids->video.pid, p_pids->video.format,
1726 p_pids->audio.pid, p_pids->audio.format,
1727 p_pids->ad.pid, p_pids->ad.format,
1728 p_pids->subtitle.pid, p_pids->subtitle.format,
1729 p_pids->pcr.pid);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001730
Gong Kefdb31922022-06-17 17:11:16 +08001731 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001732
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001733 if (ctx->playback.param_open.is_timeshift) {
1734 /*lock the recorder to avoid changing the recording segments*/
hualing chenc110f952021-01-18 11:25:37 +08001735 if (is_timeshift == DVR_FALSE) {
Wentao MA96f68962022-06-15 19:45:35 +08001736 DVR_WRAPPER_INFO("timeshift, record is not for timeshifting, FATAL error return\n");
Gong Kefdb31922022-06-17 17:11:16 +08001737 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001738 return DVR_FAILURE;
1739 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001740 DVR_WRAPPER_INFO("playback(sn:%ld) record(sn:%ld) locked ok due to timeshift\n",
hualing chenc110f952021-01-18 11:25:37 +08001741 ctx->sn, ctx_record->sn);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001742 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001743 }
1744
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001745 /*obtain all segments in a list*/
1746 segment_nb = 0;
1747 p_segment_ids = NULL;
1748 error = dvr_segment_get_list(ctx->playback.param_open.location, &segment_nb, &p_segment_ids);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001749 if (!error) {
1750 got_1st_seg = 0;
hualing chenb9a02922021-12-14 11:29:47 +08001751 struct list_head info_list; /**< segment list head*/
1752 INIT_LIST_HEAD(&info_list);
1753
Wentao MA96f68962022-06-15 19:45:35 +08001754 DVR_WRAPPER_INFO("get list segment_nb::%d",segment_nb);
hualing chenb9a02922021-12-14 11:29:47 +08001755 //we need free info list buf when we used end.
1756 error = dvr_segment_get_allInfo(ctx->playback.param_open.location, &info_list);
hualing chen926a8ec2021-12-20 20:38:24 +08001757 if (error == DVR_FAILURE) {
hualing chenb9a02922021-12-14 11:29:47 +08001758 error = DVR_FAILURE;
Zhiqiang Handc3bfe52022-07-07 10:48:39 +08001759 DVR_WRAPPER_INFO("fail to get all seg info (location:%s), (error:%d)\n",
1760 ctx->playback.param_open.location, error);
wentao.maf57dd232022-10-08 16:07:29 +08001761 // Tainted data issue originating from fgets seem false positive, so we
1762 // just suppress it here.
1763 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08001764 for (i = 0; i < segment_nb; i++) {
1765 DVR_RecordSegmentInfo_t seg_info;
Wentao MA4d85ff32022-09-23 11:36:18 +08001766 memset((void*)&seg_info,0,sizeof(seg_info));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001767
hualing chenb9a02922021-12-14 11:29:47 +08001768 error = dvr_segment_get_info(ctx->playback.param_open.location, p_segment_ids[i], &seg_info);
1769 if (error) {
1770 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08001771 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chenb9a02922021-12-14 11:29:47 +08001772 ctx->playback.param_open.location, p_segment_ids[i], error);
1773 break;
1774 }
1775 //add check if has audio or video pid. if not exist. not add segment to playback
1776 int ii = 0;
1777 int has_av = 0;
wentao.maf57dd232022-10-08 16:07:29 +08001778 // Tainted data issue originating from fgets seem false positive, so we
1779 // just suppress it here.
1780 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08001781 for (ii = 0; ii < seg_info.nb_pids; ii++) {
1782 int type = (seg_info.pids[ii].type >> 24) & 0x0f;
1783 if (type == DVR_STREAM_TYPE_VIDEO ||
1784 type == DVR_STREAM_TYPE_AUDIO ||
1785 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001786 DVR_WRAPPER_INFO("success to get seg av info \n");
1787 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 +08001788 DVR_STREAM_TYPE_VIDEO,
1789 DVR_STREAM_TYPE_AUDIO,
1790 DVR_STREAM_TYPE_AD);
1791 has_av = 1;
1792 //break;
1793 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001794 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 +08001795 DVR_STREAM_TYPE_VIDEO,
1796 DVR_STREAM_TYPE_AUDIO,
1797 DVR_STREAM_TYPE_AD);
1798 }
1799 }
1800 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001801 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001802 continue;
1803 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001804 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001805 }
Wentao MAcefc13c2022-10-26 15:47:24 +08001806 seg_flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
1807 error = wrapper_addPlaybackSegment(ctx, &seg_info, p_pids, seg_flags);
wentao.maa210e5e2022-10-12 16:10:03 +08001808 if (error == DVR_FAILURE) {
1809 DVR_WRAPPER_WARN("adding playback segment fails");
hualing chenb9a02922021-12-14 11:29:47 +08001810 break;
wentao.maa210e5e2022-10-12 16:10:03 +08001811 }
hualing chenb9a02922021-12-14 11:29:47 +08001812 /*copy the 1st segment*/
1813 if (got_1st_seg == 0) {
1814 seg_info_1st = seg_info;
1815 got_1st_seg = 1;
1816 }
1817 }
1818 } else {
wentao.maf57dd232022-10-08 16:07:29 +08001819 // Tainted data issue originating from fgets seem false positive, so we
1820 // just suppress it here.
1821 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08001822 for (i = 0; i < segment_nb; i++) {
Wentao MA4d85ff32022-09-23 11:36:18 +08001823 DVR_RecordSegmentInfo_t *p_seg_info;
hualing chenb9a02922021-12-14 11:29:47 +08001824 int found = 0;
wentao.mafd5283f2022-10-14 09:51:13 +08001825 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08001826 // prefetch() here incurring self_assign is used to avoid some compiling
1827 // warnings.
1828 // coverity[self_assign]
Wentao MA4d85ff32022-09-23 11:36:18 +08001829 list_for_each_entry(p_seg_info, &info_list, head)
hualing chenb9a02922021-12-14 11:29:47 +08001830 {
Wentao MA4d85ff32022-09-23 11:36:18 +08001831 if (p_seg_info->id == p_segment_ids[i]) {
hualing chenb9a02922021-12-14 11:29:47 +08001832 found = 1;
Wentao MA96f68962022-06-15 19:45:35 +08001833 DVR_WRAPPER_INFO("get segment info::%d", i);
hualing chenb9a02922021-12-14 11:29:47 +08001834 break;
1835 }
1836 }
1837 if (!found) {
hualing chen8aed9582021-12-24 17:59:56 +08001838 //last info is not found if when recording occured power off.
1839 if (p_segment_ids[i] == segment_nb - 1) {
1840 DVR_RecordSegmentInfo_t seg_info;
Wentao MA4d85ff32022-09-23 11:36:18 +08001841 memset((void*)&seg_info,0,sizeof(seg_info));
hualing chen8aed9582021-12-24 17:59:56 +08001842
1843 error = dvr_segment_get_info(ctx->playback.param_open.location, p_segment_ids[i], &seg_info);
1844 if (error) {
1845 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08001846 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chen8aed9582021-12-24 17:59:56 +08001847 ctx->playback.param_open.location, p_segment_ids[i], error);
1848 break;
1849 }
1850 //
1851 //add check if has audio or video pid. if not exist. not add segment to playback
1852 int ii = 0;
1853 int has_av = 0;
wentao.maf57dd232022-10-08 16:07:29 +08001854 // Tainted data issue originating from fgets seem false positive, so we
1855 // just suppress it here.
1856 // coverity[tainted_data]
hualing chen8aed9582021-12-24 17:59:56 +08001857 for (ii = 0; ii < seg_info.nb_pids; ii++) {
1858 int type = (seg_info.pids[ii].type >> 24) & 0x0f;
1859 if (type == DVR_STREAM_TYPE_VIDEO ||
1860 type == DVR_STREAM_TYPE_AUDIO ||
1861 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001862 DVR_WRAPPER_INFO("success to get seg av info \n");
1863 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 +08001864 DVR_STREAM_TYPE_VIDEO,
1865 DVR_STREAM_TYPE_AUDIO,
1866 DVR_STREAM_TYPE_AD);
1867 has_av = 1;
1868 //break;
1869 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001870 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 +08001871 DVR_STREAM_TYPE_VIDEO,
1872 DVR_STREAM_TYPE_AUDIO,
1873 DVR_STREAM_TYPE_AD);
1874 }
1875 }
1876 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001877 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chen8aed9582021-12-24 17:59:56 +08001878 continue;
1879 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001880 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chen8aed9582021-12-24 17:59:56 +08001881 }
Wentao MAcefc13c2022-10-26 15:47:24 +08001882 seg_flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
1883 error = wrapper_addPlaybackSegment(ctx, &seg_info, p_pids, seg_flags);
wentao.maa210e5e2022-10-12 16:10:03 +08001884 if (error == DVR_FAILURE) {
1885 DVR_WRAPPER_WARN("adding playback segment fails");
hualing chen8aed9582021-12-24 17:59:56 +08001886 break;
wentao.maa210e5e2022-10-12 16:10:03 +08001887 }
hualing chen8aed9582021-12-24 17:59:56 +08001888 }
hualing chenb9a02922021-12-14 11:29:47 +08001889 continue;
1890 }
1891
1892 //add check if has audio or video pid. if not exist. not add segment to playback
1893 int ii = 0;
1894 int has_av = 0;
Wentao MA4d85ff32022-09-23 11:36:18 +08001895 for (ii = 0; ii < p_seg_info->nb_pids; ii++) {
1896 int type = (p_seg_info->pids[ii].type >> 24) & 0x0f;
hualing chenb9a02922021-12-14 11:29:47 +08001897 if (type == DVR_STREAM_TYPE_VIDEO ||
1898 type == DVR_STREAM_TYPE_AUDIO ||
1899 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001900 DVR_WRAPPER_INFO("success to get seg av info \n");
Wentao MA4d85ff32022-09-23 11:36:18 +08001901 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 +08001902 DVR_STREAM_TYPE_VIDEO,
1903 DVR_STREAM_TYPE_AUDIO,
1904 DVR_STREAM_TYPE_AD);
1905 has_av = 1;
1906 //break;
1907 } else {
Wentao MA4d85ff32022-09-23 11:36:18 +08001908 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 +08001909 DVR_STREAM_TYPE_VIDEO,
1910 DVR_STREAM_TYPE_AUDIO,
1911 DVR_STREAM_TYPE_AD);
1912 }
1913 }
1914 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001915 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001916 continue;
1917 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001918 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001919 }
Wentao MAcefc13c2022-10-26 15:47:24 +08001920 seg_flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
1921 error = wrapper_addPlaybackSegment(ctx, p_seg_info, p_pids, seg_flags);
wentao.maa210e5e2022-10-12 16:10:03 +08001922 if (error == DVR_FAILURE) {
1923 DVR_WRAPPER_WARN("adding playback segment fails");
hualing chenb9a02922021-12-14 11:29:47 +08001924 break;
wentao.maa210e5e2022-10-12 16:10:03 +08001925 }
hualing chenb9a02922021-12-14 11:29:47 +08001926
1927 /*copy the 1st segment*/
1928 if (got_1st_seg == 0) {
Wentao MA4d85ff32022-09-23 11:36:18 +08001929 seg_info_1st = *p_seg_info;
hualing chenb9a02922021-12-14 11:29:47 +08001930 got_1st_seg = 1;
1931 }
hualing chen92f3a142020-07-08 20:59:33 +08001932 }
hualing chenb9a02922021-12-14 11:29:47 +08001933 //free list
1934 DVR_RecordSegmentInfo_t *segment = NULL;
1935 DVR_RecordSegmentInfo_t *segment_tmp = NULL;
1936 list_for_each_entry_safe(segment, segment_tmp, &info_list, head)
1937 {
1938 if (segment) {
1939 list_del(&segment->head);
1940 free(segment);
1941 }
1942 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001943 }
hualing chenb9a02922021-12-14 11:29:47 +08001944
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001945 free(p_segment_ids);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001946
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001947 /* return if no segment or fail to add */
1948 if (!error && got_1st_seg) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001949
Wentao MA270dc0f2022-08-23 13:17:26 +08001950 /*copy the obsolete information, must for timeshifting*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001951 if (ctx->playback.param_open.is_timeshift && ctx_record) {
1952 ctx->playback.obsolete = ctx_record->record.obsolete;
1953 }
1954
Wentao MA96f68962022-06-15 19:45:35 +08001955 DVR_WRAPPER_INFO("playback(sn:%ld) (%d) segments added\n", ctx->sn, i);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001956
1957 ctx->playback.reach_end = DVR_FALSE;
1958 if ((flags&DVR_PLAYBACK_STARTED_PAUSEDLIVE) == DVR_PLAYBACK_STARTED_PAUSEDLIVE)
1959 ctx->playback.speed = 0.0f;
1960 else
1961 ctx->playback.speed = 100.0f;
1962
1963 ctx->playback.pids_req = *p_pids;
Wentao MA270dc0f2022-08-23 13:17:26 +08001964 //calculate segment id and pos
hualing chen03fd4942021-07-15 15:56:41 +08001965 if (dvr_playback_check_limit(ctx->playback.player)) {
Gong Kefdb31922022-06-17 17:11:16 +08001966 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001967 dvr_wrapper_seek_playback(playback, 0);
Gong Kefdb31922022-06-17 17:11:16 +08001968 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001969 error = dvr_playback_start(ctx->playback.player, flags);
1970 } else {
wentao.maa210e5e2022-10-12 16:10:03 +08001971 dvr_playback_seek(ctx->playback.player, seg_info_1st.id, 0);
hualing chen03fd4942021-07-15 15:56:41 +08001972 error = dvr_playback_start(ctx->playback.player, flags);
Wentao MA96f68962022-06-15 19:45:35 +08001973 DVR_WRAPPER_INFO("playback(sn:%ld) seek(seg:%llu 0) for start (%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08001974 ctx->sn, seg_info_1st.id, error);
1975 }
Wentao MA96f68962022-06-15 19:45:35 +08001976 DVR_WRAPPER_INFO("playback(sn:%ld) started (%d)\n", ctx->sn, error);
hualing chen451c8f72022-03-09 13:05:52 +08001977 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001978 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 +08001979 }
1980 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001981
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001982 if (ctx->playback.param_open.is_timeshift) {
1983 /*unlock the recorder locked above*/
1984 if (ctx_record && ctx_valid(ctx_record)) {
Gong Kefdb31922022-06-17 17:11:16 +08001985 wrapper_mutex_unlock(&ctx_record->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001986 DVR_WRAPPER_INFO("playback(sn:%ld), record(sn:%ld) unlocked ok due to timeshift\n",
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001987 ctx->sn, ctx_record->sn);
1988 }
1989 }
Gong Kefdb31922022-06-17 17:11:16 +08001990 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001991
1992 return error;
1993}
hualing chen002e5b92022-02-23 17:51:21 +08001994//stop record and playback
1995int dvr_wrapper_stop_timeshift (DVR_WrapperPlayback_t playback)
1996{
1997 DVR_WrapperCtx_t *ctx_record = NULL;/*for timeshift*/
1998 int error;
Wentao MA804bab12022-11-29 10:01:26 +08001999 DVR_WRAPPER_INFO("libdvr_api, stop_timeshift");
hualing chen002e5b92022-02-23 17:51:21 +08002000
2001 //stop timeshift record
2002 ctx_record = ctx_getRecord(sn_timeshift_record);
wentao.maa210e5e2022-10-12 16:10:03 +08002003 dvr_wrapper_stop_record((DVR_WrapperRecord_t)sn_timeshift_record);
hualing chen002e5b92022-02-23 17:51:21 +08002004
Wentao MA96f68962022-06-15 19:45:35 +08002005 DVR_WRAPPER_INFO("stop timeshift ...stop play\n");
hualing chen002e5b92022-02-23 17:51:21 +08002006 //stop play
2007 error = dvr_wrapper_stop_playback(playback);
2008 //del timeshift file
2009 if (ctx_record != NULL) {
Wentao MA96f68962022-06-15 19:45:35 +08002010 DVR_WRAPPER_INFO("del timeshift(sn:%ld) ...3\n", ctx_record->sn);
hualing chen002e5b92022-02-23 17:51:21 +08002011 error = dvr_segment_del_by_location(ctx_record->record.param_open.location);
2012 }
2013 return error;
2014}
2015//start record and start playback
2016int dvr_wrapper_restart_timeshift(DVR_WrapperPlayback_t playback, DVR_PlaybackFlag_t flags, DVR_PlaybackPids_t *p_pids)
2017{
2018 DVR_WrapperCtx_t *ctx;
2019 DVR_RecordStartParams_t *start_param;
2020 int error;
2021
2022 ctx = ctx_getRecord((unsigned long)sn_timeshift_record);
2023 DVR_RETURN_IF_FALSE(ctx);
2024
Gong Kefdb31922022-06-17 17:11:16 +08002025 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08002026 DVR_WRAPPER_INFO("libdvr_api, restart_timeshift (sn:%ld) location:%s",
2027 ctx->sn, ctx->record.param_open.location);
Gong Kefdb31922022-06-17 17:11:16 +08002028 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen002e5b92022-02-23 17:51:21 +08002029
hualing chen451c8f72022-03-09 13:05:52 +08002030 {
2031 //clear old record status
2032 // struct {
2033 // DVR_WrapperRecordOpenParams_t param_open;
2034 // DVR_RecordStartParams_t param_start;
2035 // DVR_RecordStartParams_t param_update;
2036 // DVR_RecordHandle_t recorder;
2037 // DVR_RecordEventFunction_t event_fn;
2038 // void *event_userdata;
2039
2040 // /*total status = seg_status + status + obsolete*/
2041 // DVR_RecordStatus_t seg_status; /**<status of current segment*/
2042 // DVR_WrapperRecordStatus_t status; /**<status of remaining segments*/
2043 // uint64_t next_segment_id;
2044
2045 // DVR_WrapperInfo_t obsolete; /**<data obsolete due to the max limit*/
2046 // } record;
2047 memset(&(ctx->record.seg_status), 0, sizeof(DVR_RecordStatus_t));
2048 memset(&(ctx->record.status), 0, sizeof(DVR_WrapperRecordStatus_t));
2049 memset(&(ctx->record.obsolete), 0, sizeof(DVR_WrapperInfo_t));
2050 }
2051
hualing chen002e5b92022-02-23 17:51:21 +08002052 start_param = &ctx->record.param_start;
2053
2054 error = dvr_record_start_segment(ctx->record.recorder, start_param);
2055 {
2056 DVR_RecordSegmentInfo_t new_seg_info =
2057 { .id = start_param->segment.segment_id, };
2058 wrapper_addRecordSegment(ctx, &new_seg_info);
Wentao MA96f68962022-06-15 19:45:35 +08002059 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 +08002060 ctx->record.next_segment_id = start_param->segment.segment_id + 1;
2061 DVR_RecordStartParams_t *update_param;
2062 update_param = &ctx->record.param_update;
2063 memcpy(update_param, start_param, sizeof(*update_param));
2064 int i = 0;
2065 for (i = 0; i < update_param->segment.nb_pids; i++)
2066 update_param->segment.pid_action[i] = DVR_RECORD_PID_KEEP;
hualing chen002e5b92022-02-23 17:51:21 +08002067 }
2068
Wentao MA96f68962022-06-15 19:45:35 +08002069 DVR_WRAPPER_INFO("re record(sn:%ld) started = (%d)\n", ctx->sn, error);
hualing chen002e5b92022-02-23 17:51:21 +08002070
Gong Kefdb31922022-06-17 17:11:16 +08002071 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen002e5b92022-02-23 17:51:21 +08002072
2073 //start play
Wentao MA96f68962022-06-15 19:45:35 +08002074 DVR_WRAPPER_INFO("re start play and clear old status\n");
hualing chen451c8f72022-03-09 13:05:52 +08002075 //clear play statue
2076 ctx = ctx_getPlayback((unsigned long)playback);
2077 if (ctx) {
Wentao MA4d85ff32022-09-23 11:36:18 +08002078 //reset old playback status
hualing chen451c8f72022-03-09 13:05:52 +08002079 // struct {
2080 // DVR_WrapperPlaybackOpenParams_t param_open;
2081 // DVR_PlaybackHandle_t player;
2082 // DVR_PlaybackEventFunction_t event_fn;
2083 // void *event_userdata;
2084
2085 // /*total status = seg_status + status*/
2086 // DVR_PlaybackStatus_t seg_status;
2087 // DVR_WrapperPlaybackStatus_t status;
2088 // DVR_PlaybackPids_t pids_req;
2089 // DVR_PlaybackEvent_t last_event;
2090 // float speed;
2091 // DVR_Bool_t reach_end;
2092
2093 // DVR_WrapperInfo_t obsolete;
2094 // DVR_Bool_t tf_full;
2095 // } playback;
Wentao MA4d85ff32022-09-23 11:36:18 +08002096 ctx->playback.tf_full = DVR_FALSE;
2097 ctx->playback.reach_end = DVR_FALSE;
hualing chen451c8f72022-03-09 13:05:52 +08002098 memset(&(ctx->playback.last_event), 0, sizeof(DVR_PlaybackEvent_t));
2099 memset(&(ctx->playback.seg_status), 0, sizeof(DVR_PlaybackStatus_t));
2100 memset(&(ctx->playback.status), 0, sizeof(DVR_WrapperPlaybackStatus_t));
2101 memset(&(ctx->playback.obsolete), 0, sizeof(DVR_WrapperInfo_t));
2102 }
hualing chen002e5b92022-02-23 17:51:21 +08002103 error = dvr_wrapper_start_playback(playback, flags, p_pids);
2104 return error;
2105}
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002106
2107int dvr_wrapper_stop_playback (DVR_WrapperPlayback_t playback)
2108{
2109 DVR_WrapperCtx_t *ctx;
2110 int error;
2111
2112 DVR_RETURN_IF_FALSE(playback);
2113
2114 ctx = ctx_getPlayback((unsigned long)playback);
2115 DVR_RETURN_IF_FALSE(ctx);
2116
Gong Kefdb31922022-06-17 17:11:16 +08002117 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08002118 DVR_WRAPPER_INFO("libdvr_api, stop_playback (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002119 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002120
2121 error = dvr_playback_stop(ctx->playback.player, DVR_TRUE);
2122
2123 {
2124 /*remove all segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002125 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002126
wentao.mafd5283f2022-10-14 09:51:13 +08002127 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08002128 // prefetch() here incurring self_assign is used to avoid some compiling
2129 // warnings.
2130 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002131 list_for_each_entry(p_seg, &ctx->segments, head) {
2132 error = dvr_playback_remove_segment(ctx->playback.player, p_seg->playback_info.segment_id);
Wentao MA96f68962022-06-15 19:45:35 +08002133 DVR_WRAPPER_INFO("playback(sn:%ld) remove seg(%lld) (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08002134 ctx->sn, p_seg->playback_info.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002135 }
2136 ctx_freeSegments(ctx);
2137 }
2138
Wentao MA96f68962022-06-15 19:45:35 +08002139 DVR_WRAPPER_INFO("playback(sn:%ld) stopped (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002140 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002141
2142 return error;
2143}
2144
2145int dvr_wrapper_pause_playback (DVR_WrapperPlayback_t playback)
2146{
2147 DVR_WrapperCtx_t *ctx;
2148 int error;
2149
2150 DVR_RETURN_IF_FALSE(playback);
2151
2152 ctx = ctx_getPlayback((unsigned long)playback);
2153 DVR_RETURN_IF_FALSE(ctx);
2154
Gong Kefdb31922022-06-17 17:11:16 +08002155 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08002156 DVR_WRAPPER_INFO("libdvr_api, pause_playback (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002157 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen36e0dfd2020-05-02 16:33:06 +08002158 //clear end event
Zhiqiang Hanb723cdb2020-05-09 11:10:29 +08002159 if (ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_END)
hualing chen36e0dfd2020-05-02 16:33:06 +08002160 ctx->playback.last_event = DVR_PLAYBACK_EVENT_TRANSITION_OK;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002161
2162 error = dvr_playback_pause(ctx->playback.player, DVR_FALSE);
2163
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002164 ctx->playback.speed = 0.0f;
2165
Wentao MA96f68962022-06-15 19:45:35 +08002166 DVR_WRAPPER_INFO("playback(sn:%ld) paused (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002167 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002168
2169 return error;
2170}
2171
2172int dvr_wrapper_resume_playback (DVR_WrapperPlayback_t playback)
2173{
2174 DVR_WrapperCtx_t *ctx;
2175 int error;
2176
2177 DVR_RETURN_IF_FALSE(playback);
2178
2179 ctx = ctx_getPlayback((unsigned long)playback);
2180 DVR_RETURN_IF_FALSE(ctx);
hualing chen03fd4942021-07-15 15:56:41 +08002181 //if set limit.we need check if seek to valid data when resume
2182 uint32_t time_offset = ctx->playback.status.info_cur.time + ctx->playback.status.info_obsolete.time;
2183 if (dvr_playback_check_limit(ctx->playback.player)) {
2184 int expired = dvr_playback_calculate_expiredlen(ctx->playback.player);
2185 if (expired > time_offset) {
Wentao MA96f68962022-06-15 19:45:35 +08002186 DVR_WRAPPER_INFO("seek before resume reset offset playback(sn:%ld) (off:%d expired:%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08002187 ctx->sn, time_offset, expired);
2188 time_offset = expired;
2189 dvr_wrapper_seek_playback(playback, time_offset);
2190 }
2191 }
Gong Kefdb31922022-06-17 17:11:16 +08002192 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08002193 DVR_WRAPPER_INFO("libdvr_api, resume_playback (sn:%ld)", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002194 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002195
2196 error = dvr_playback_resume(ctx->playback.player);
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002197 ctx->playback.speed = 100.0f;
2198
Wentao MA96f68962022-06-15 19:45:35 +08002199 DVR_WRAPPER_INFO("playback(sn:%ld) resumed (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002200 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002201
2202 return error;
2203}
2204
2205int dvr_wrapper_set_playback_speed (DVR_WrapperPlayback_t playback, float speed)
2206{
2207 DVR_WrapperCtx_t *ctx;
2208 int error;
2209 DVR_PlaybackSpeed_t dvr_speed = {
2210 .speed = { speed },
2211 .mode = (speed > 0) ? DVR_PLAYBACK_FAST_FORWARD : DVR_PLAYBACK_FAST_BACKWARD
2212 };
2213
2214 DVR_RETURN_IF_FALSE(playback);
2215
2216 ctx = ctx_getPlayback((unsigned long)playback);
2217 DVR_RETURN_IF_FALSE(ctx);
2218
Gong Kefdb31922022-06-17 17:11:16 +08002219 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA804bab12022-11-29 10:01:26 +08002220 DVR_WRAPPER_INFO("libdvr_api, set_playback_speed (sn:%ld) speed:%d", ctx->sn, (int)speed);
Gong Kefdb31922022-06-17 17:11:16 +08002221 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002222
2223 error = dvr_playback_set_speed(ctx->playback.player, dvr_speed);
2224
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002225 if (ctx->playback.speed != 0.0f && ctx->playback.speed != 100.0f
2226 && ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_BEGIN
2227 && ctx->playback.seg_status.state == DVR_PLAYBACK_STATE_PAUSE) {
Wentao MA96f68962022-06-15 19:45:35 +08002228 DVR_WRAPPER_INFO("x%f -> x%f, paused, do resume first\n", ctx->playback.speed, speed);
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002229 error = dvr_playback_resume(ctx->playback.player);
2230 } else if (ctx->playback.speed == 0.0f
2231 && speed != 0.0f
2232 && speed != 100.0f) {
2233 /*libdvr do not support pause with speed=0, will not be here*/
Wentao MA96f68962022-06-15 19:45:35 +08002234 DVR_WRAPPER_INFO("x%f -> x%f, do resume first\n", ctx->playback.speed, speed);
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002235 error = dvr_playback_resume(ctx->playback.player);
2236 }
2237
2238 ctx->playback.speed = speed;
2239
Wentao MA96f68962022-06-15 19:45:35 +08002240 DVR_WRAPPER_INFO("playback(sn:%ld) speeded(x%f) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002241 ctx->sn, speed, error);
Gong Kefdb31922022-06-17 17:11:16 +08002242 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002243
2244 return error;
2245}
2246
hualing chen03fd4942021-07-15 15:56:41 +08002247int dvr_wrapper_setlimit_playback (DVR_WrapperPlayback_t playback, uint64_t time, int32_t limit)
2248{
2249 DVR_WrapperCtx_t *ctx;
2250 int error;
2251
2252 DVR_RETURN_IF_FALSE(playback);
2253
2254 ctx = ctx_getPlayback((unsigned long)playback);
2255 DVR_RETURN_IF_FALSE(ctx);
2256
Gong Kefdb31922022-06-17 17:11:16 +08002257 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002258
Wentao MA804bab12022-11-29 10:01:26 +08002259 DVR_WRAPPER_INFO("libdvr_api, setlimit_playback (sn:%ld) time:%lld, limit:%d",
2260 ctx->sn, time, limit);
Gong Kefdb31922022-06-17 17:11:16 +08002261 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002262
2263 error = dvr_playback_setlimit(ctx->playback.player, time, limit);
Wentao MAe8ba5172022-08-09 11:18:17 +08002264 DVR_WRAPPER_INFO("playback(sn:%ld) set_limit(time:%lld limit:%d) ...\n", ctx->sn, time, limit);
hualing chen03fd4942021-07-15 15:56:41 +08002265
Gong Kefdb31922022-06-17 17:11:16 +08002266 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002267
2268 return error;
2269}
2270
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002271int dvr_wrapper_seek_playback (DVR_WrapperPlayback_t playback, uint32_t time_offset)
2272{
2273 DVR_WrapperCtx_t *ctx;
2274 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08002275 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Wentao MA804bab12022-11-29 10:01:26 +08002276 uint64_t segment_id = ULLONG_MAX;
2277 uint32_t segment_offset = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002278
2279 DVR_RETURN_IF_FALSE(playback);
2280
2281 ctx = ctx_getPlayback((unsigned long)playback);
2282 DVR_RETURN_IF_FALSE(ctx);
2283
Gong Kefdb31922022-06-17 17:11:16 +08002284 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002285
Wentao MA804bab12022-11-29 10:01:26 +08002286 DVR_WRAPPER_INFO("libdvr_api, seek_playback (sn:%ld) offset:%dms", ctx->sn, time_offset);
Gong Kefdb31922022-06-17 17:11:16 +08002287 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002288
hualing chen03fd4942021-07-15 15:56:41 +08002289 //if set limit info we need check ts data is
2290 //expired when seek
2291 if (dvr_playback_check_limit(ctx->playback.player)) {
2292 int expired = dvr_playback_calculate_expiredlen(ctx->playback.player);
2293 if (expired > time_offset) {
Wentao MA96f68962022-06-15 19:45:35 +08002294 DVR_WRAPPER_INFO("seek reset offset playback(sn:%ld) (off:%d expired:%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08002295 ctx->sn, time_offset, expired);
2296 time_offset = expired;
2297 }
2298 }
2299
Wentao MA804bab12022-11-29 10:01:26 +08002300 const uint32_t obsolete_time = (uint32_t)ctx->playback.obsolete.time;
2301 DVR_WrapperPlaybackSegmentInfo_t *p_seg_first = ctx->segments.c_prev;
2302 DVR_WrapperPlaybackSegmentInfo_t *p_seg_last = ctx->segments.c_next;
2303 const uint64_t first_id = p_seg_first->seg_info.id;
2304 const uint64_t last_id = p_seg_last->seg_info.id;
2305 const uint32_t last_duration = p_seg_last->seg_info.duration;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002306
Wentao MA804bab12022-11-29 10:01:26 +08002307 if (time_offset <= obsolete_time) {
2308 segment_id = first_id;
2309 segment_offset = 0;
2310 DVR_WRAPPER_WARN("time_offset %u isn't greater than obsolete time %u, "
2311 "so seek to beginning position of segment %llu",
2312 time_offset,obsolete_time,segment_id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002313 } else {
Wentao MA804bab12022-11-29 10:01:26 +08002314 uint32_t total_duration = 0;
2315 // This error is suppressed as the macro code is picked from kernel.
2316 // prefetch() here incurring self_assign is used to avoid some compiling
2317 // warnings.
2318 // coverity[self_assign]
2319 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
2320 const uint32_t segment_begin = obsolete_time + total_duration;
2321 const uint32_t segment_end = segment_begin + p_seg->seg_info.duration;
2322 if (time_offset >= segment_begin && time_offset <= segment_end) {
2323 segment_id = p_seg->seg_info.id;
2324 segment_offset = time_offset - segment_begin;
2325 break;
2326 }
2327 total_duration += p_seg->seg_info.duration;
2328 }
2329 if (segment_id == ULLONG_MAX) {
2330 segment_id = last_id;
2331 segment_offset = last_duration;
2332 DVR_WRAPPER_WARN("time_offset %u is out of range, so seek to"
2333 " the end position of segment %llu",time_offset,segment_id);
2334 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002335 }
2336
Wentao MA804bab12022-11-29 10:01:26 +08002337 DVR_WRAPPER_INFO("seek playback(sn:%ld) (segment_id:%llu, segment_offset:%u)\n",
2338 ctx->sn, segment_id, segment_offset);
2339 error = dvr_playback_seek(ctx->playback.player, segment_id, segment_offset);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002340
Gong Kefdb31922022-06-17 17:11:16 +08002341 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002342
2343 return error;
2344}
2345
2346int dvr_wrapper_update_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackPids_t *p_pids)
2347{
2348 DVR_WrapperCtx_t *ctx;
2349 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08002350 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002351
2352 DVR_RETURN_IF_FALSE(playback);
2353 DVR_RETURN_IF_FALSE(p_pids);
2354
2355 ctx = ctx_getPlayback((unsigned long)playback);
2356 DVR_RETURN_IF_FALSE(ctx);
2357
Gong Kefdb31922022-06-17 17:11:16 +08002358 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002359
Wentao MA804bab12022-11-29 10:01:26 +08002360 DVR_WRAPPER_INFO("libdvr_api, update_playback (sn:%ld) v/a(%d:%d/%d:%d)",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002361 ctx->sn,
2362 p_pids->video.pid, p_pids->video.format,
2363 p_pids->audio.pid, p_pids->audio.format);
Gong Kefdb31922022-06-17 17:11:16 +08002364 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002365
2366 ctx->playback.pids_req = *p_pids;
2367
2368 error = 0;
wentao.mafd5283f2022-10-14 09:51:13 +08002369 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08002370 // prefetch() here incurring self_assign is used to avoid some compiling
2371 // warnings.
2372 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002373 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002374 /*should update the whole list of segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002375 /*if (p_seg->seg_info.id == ctx->current_segment_id)*/ {
2376 /*list_for_each_entry_from(p_seg, &ctx->segments, head)*/ {
2377 /*check update for pids*/
2378 if (memcmp(&p_seg->playback_info.pids, p_pids, sizeof(*p_pids)) != 0) {
2379 p_seg->playback_info.pids = *p_pids;
2380 error = dvr_playback_update_segment_pids(ctx->playback.player, p_seg->seg_info.id, p_pids);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002381 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08002382 DVR_WRAPPER_INFO("failed to playback(sn:%ld) update segment(id:%lld) pids (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08002383 ctx->sn, p_seg->seg_info.id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002384 /*do not break, let list updated*/
2385 }
2386 }
2387 }
2388 /*break;*/
2389 }
2390 }
2391
Wentao MA96f68962022-06-15 19:45:35 +08002392 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002393 ctx->sn,
2394 p_pids->video.pid, p_pids->video.format,
2395 p_pids->audio.pid, p_pids->audio.format,
2396 error);
2397
Gong Kefdb31922022-06-17 17:11:16 +08002398 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002399
2400 return error;
2401}
2402
hualing chena5f03222021-12-02 11:22:35 +08002403int dvr_wrapper_only_update_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackPids_t *p_pids)
2404{
2405 DVR_WrapperCtx_t *ctx;
2406 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08002407 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
hualing chena5f03222021-12-02 11:22:35 +08002408
2409 DVR_RETURN_IF_FALSE(playback);
2410 DVR_RETURN_IF_FALSE(p_pids);
2411
2412 ctx = ctx_getPlayback((unsigned long)playback);
2413 DVR_RETURN_IF_FALSE(ctx);
2414
Gong Kefdb31922022-06-17 17:11:16 +08002415 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002416
Wentao MA804bab12022-11-29 10:01:26 +08002417 DVR_WRAPPER_INFO("libdvr_api, only_update_playback (sn:%ld) v/a(%d:%d/%d:%d)",
hualing chena5f03222021-12-02 11:22:35 +08002418 ctx->sn,
2419 p_pids->video.pid, p_pids->video.format,
2420 p_pids->audio.pid, p_pids->audio.format);
Gong Kefdb31922022-06-17 17:11:16 +08002421 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002422
2423 ctx->playback.pids_req = *p_pids;
2424
2425 error = 0;
wentao.mafd5283f2022-10-14 09:51:13 +08002426 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08002427 // prefetch() here incurring self_assign is used to avoid some compiling
2428 // warnings.
2429 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002430 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
hualing chena5f03222021-12-02 11:22:35 +08002431 /*should update the whole list of segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002432 /*if (p_seg->seg_info.id == ctx->current_segment_id)*/ {
2433 /*list_for_each_entry_from(p_seg, &ctx->segments, head)*/ {
2434 /*check update for pids*/
2435 if (memcmp(&p_seg->playback_info.pids, p_pids, sizeof(*p_pids)) != 0) {
2436 p_seg->playback_info.pids = *p_pids;
2437 error = dvr_playback_only_update_segment_pids(ctx->playback.player, p_seg->seg_info.id, p_pids);
hualing chena5f03222021-12-02 11:22:35 +08002438 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08002439 DVR_WRAPPER_INFO("failed to playback(sn:%ld) update segment(id:%lld) pids (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08002440 ctx->sn, p_seg->seg_info.id, error);
hualing chena5f03222021-12-02 11:22:35 +08002441 /*do not break, let list updated*/
2442 }
2443 }
2444 }
2445 /*break;*/
2446 }
2447 }
2448
Wentao MA96f68962022-06-15 19:45:35 +08002449 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) (%d)\n",
hualing chena5f03222021-12-02 11:22:35 +08002450 ctx->sn,
2451 p_pids->video.pid, p_pids->video.format,
2452 p_pids->audio.pid, p_pids->audio.format,
2453 error);
2454
Gong Kefdb31922022-06-17 17:11:16 +08002455 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002456
2457 return error;
2458}
2459
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002460int dvr_wrapper_get_playback_status(DVR_WrapperPlayback_t playback, DVR_WrapperPlaybackStatus_t *status)
2461{
2462 DVR_WrapperCtx_t *ctx;
2463 DVR_WrapperPlaybackStatus_t s;
2464 DVR_PlaybackStatus_t play_status;
2465 int error;
2466
2467 DVR_RETURN_IF_FALSE(playback);
2468 DVR_RETURN_IF_FALSE(status);
2469
2470 ctx = ctx_getPlayback((unsigned long)playback);
2471 DVR_RETURN_IF_FALSE(ctx);
2472
Gong Kefdb31922022-06-17 17:11:16 +08002473 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002474
Gong Kefdb31922022-06-17 17:11:16 +08002475 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002476
Wentao MA804bab12022-11-29 10:01:26 +08002477 dvr_playback_get_status(ctx->playback.player, &play_status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002478
2479 ctx->playback.seg_status = play_status;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002480 error = process_generatePlaybackStatus(ctx, &s);
2481
hualing chenb5cd42e2020-04-15 17:03:34 +08002482 if (ctx->playback.reach_end == DVR_TRUE && ctx->playback.param_open.is_timeshift == DVR_FALSE) {
2483 //reach end need set full time to cur.so app can exist playback.
Wentao MA96f68962022-06-15 19:45:35 +08002484 DVR_WRAPPER_INFO("set cur time to full time, reach end occur");
hualing chenb5cd42e2020-04-15 17:03:34 +08002485 s.info_cur.time = s.info_full.time;
2486 }
Wentao MA804bab12022-11-29 10:01:26 +08002487 DVR_WRAPPER_INFO("get_playback_status (sn:%ld) state/cur/full/obsolete(%d/%ld/%ld/%ld)",
2488 ctx->sn, s.state, s.info_cur.time, s.info_full.time, s.info_obsolete.time);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002489
2490 *status = s;
2491
Gong Kefdb31922022-06-17 17:11:16 +08002492 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002493
2494 return error;
2495}
2496
hualing chen266b9502020-04-04 17:39:39 +08002497int dvr_wrapper_set_playback_secure_buffer (DVR_WrapperPlayback_t playback, uint8_t *p_secure_buf, uint32_t len)
2498{
2499 DVR_WrapperCtx_t *ctx;
2500 int error;
2501
2502 DVR_RETURN_IF_FALSE(playback);
2503 DVR_RETURN_IF_FALSE(p_secure_buf);
2504
2505 ctx = ctx_getPlayback((unsigned long)playback);
2506 DVR_RETURN_IF_FALSE(ctx);
2507
Gong Kefdb31922022-06-17 17:11:16 +08002508 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002509 error = dvr_playback_set_secure_buffer(ctx->playback.player, p_secure_buf, len);
Gong Kefdb31922022-06-17 17:11:16 +08002510 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002511 return error;
2512}
2513
2514int dvr_wrapper_set_playback_decrypt_callback (DVR_WrapperPlayback_t playback, DVR_CryptoFunction_t func, void *userdata)
2515{
2516 DVR_WrapperCtx_t *ctx;
2517 int error;
2518
2519 DVR_RETURN_IF_FALSE(playback);
2520 DVR_RETURN_IF_FALSE(func);
2521
2522 ctx = ctx_getPlayback((unsigned long)playback);
2523 DVR_RETURN_IF_FALSE(ctx);
2524
Gong Kefdb31922022-06-17 17:11:16 +08002525 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002526 error = dvr_playback_set_decrypt_callback(ctx->playback.player, func, userdata);
Gong Kefdb31922022-06-17 17:11:16 +08002527 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002528 return error;
2529}
2530
Zhiqiang Han620b9252021-11-09 14:23:20 +08002531int dvr_wrapper_segment_del_by_location (const char *location)
2532{
2533 char fpath[DVR_MAX_LOCATION_SIZE];
2534
2535 DVR_RETURN_IF_FALSE(location);
2536
2537 /*del the stats file*/
2538 sprintf(fpath, "%s.stats", location);
2539 unlink(fpath);
2540
2541 return dvr_segment_del_by_location(location);
2542}
2543
2544int dvr_wrapper_segment_get_info_by_location (const char *location, DVR_WrapperInfo_t *p_info)
2545{
2546 FILE *fp;
2547 char fpath[DVR_MAX_LOCATION_SIZE];
2548
2549 DVR_RETURN_IF_FALSE(location);
2550 DVR_RETURN_IF_FALSE(p_info);
2551
2552 if (p_info)
2553 memset(p_info, 0, sizeof(p_info[0]));
2554
2555 memset(fpath, 0, sizeof(fpath));
2556 sprintf(fpath, "%s.stats", location);
2557
2558 /*stats file exists*/
2559 if ((fp = fopen(fpath, "r"))) {
2560 char buf[256];
2561
2562 if (fgets(buf, sizeof(buf), fp) != NULL
2563 && (sscanf(buf, ":%llu:%lu:%u",
2564 &p_info->size,
2565 &p_info->time,
2566 &p_info->pkts) == 3)) {
2567 fclose(fp);
Wentao MA96f68962022-06-15 19:45:35 +08002568 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 +08002569 return DVR_SUCCESS;
2570 }
Zhiqiang Hanb9785922021-11-26 18:47:39 +08002571 fclose(fp);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002572 }
2573
2574 /*fallback, slow on mass files*/
Wentao MA96f68962022-06-15 19:45:35 +08002575 DVR_WRAPPER_INFO("rec '%s.stats' invalid.\n", location);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002576
2577 int error;
2578 uint32_t n_ids;
2579 uint64_t *p_ids;
Zhiqiang Han620b9252021-11-09 14:23:20 +08002580
hualing chen8aed9582021-12-24 17:59:56 +08002581 error = dvr_segment_get_list(location, &n_ids, &p_ids);
hualing chenb9a02922021-12-14 11:29:47 +08002582
Zhiqiang Han620b9252021-11-09 14:23:20 +08002583 if (!error) {
2584 int i;
hualing chenb9a02922021-12-14 11:29:47 +08002585 struct list_head info_list; /**< segment list head*/
2586 INIT_LIST_HEAD(&info_list);
2587
2588 //we need free info list buf when we used end.
hualing chen8aed9582021-12-24 17:59:56 +08002589 error = dvr_segment_get_allInfo(location, &info_list);
2590 if (error == DVR_FAILURE) {
wentao.maa210e5e2022-10-12 16:10:03 +08002591 DVR_RecordSegmentInfo_t info = { .id = 0, .nb_pids = 0,
2592 .pids = {0}, .duration = 0, .size = 0, .nb_packets = 0 };
hualing chenb9a02922021-12-14 11:29:47 +08002593
2594 memset(&info, 0, sizeof(info));
2595 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08002596 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chen8aed9582021-12-24 17:59:56 +08002597 location, 0, error);
hualing chenb9a02922021-12-14 11:29:47 +08002598
wentao.maf57dd232022-10-08 16:07:29 +08002599 // Tainted data issue originating from fgets seem false positive, so we
2600 // just suppress it here.
2601 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08002602 for (i = 0; i < n_ids; i++) {
hualing chen8aed9582021-12-24 17:59:56 +08002603 error = dvr_segment_get_info(location, p_ids[i], &info);
hualing chenb9a02922021-12-14 11:29:47 +08002604 if (!error) {
2605 p_info->size += info.size;
2606 p_info->time += info.duration;
2607 p_info->pkts += info.nb_packets;
2608 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002609 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chenb9a02922021-12-14 11:29:47 +08002610 break;
2611 }
2612 }
2613 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002614 DVR_WRAPPER_INFO("get list segment_nb::%d",n_ids);
wentao.maf57dd232022-10-08 16:07:29 +08002615 // Tainted data issue originating from fgets seem false positive, so we
2616 // just suppress it here.
2617 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08002618 for (i = 0; i < n_ids; i++) {
2619
2620 DVR_RecordSegmentInfo_t *seg_info;
2621 DVR_PlaybackSegmentFlag_t flags;
2622 int found = 0;
wentao.mafd5283f2022-10-14 09:51:13 +08002623 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08002624 // prefetch() here incurring self_assign is used to avoid some compiling
2625 // warnings.
2626 // coverity[self_assign]
hualing chenb9a02922021-12-14 11:29:47 +08002627 list_for_each_entry(seg_info, &info_list, head)
2628 {
hualing chen8aed9582021-12-24 17:59:56 +08002629 if (seg_info->id == p_ids[i]) {
hualing chenb9a02922021-12-14 11:29:47 +08002630 found = 1;
2631 break;
2632 }
2633 }
2634 if (!found) {
Wentao MA96f68962022-06-15 19:45:35 +08002635 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 +08002636 if (p_ids[i] == n_ids - 1) {
wentao.maa210e5e2022-10-12 16:10:03 +08002637 DVR_RecordSegmentInfo_t info = { .id = 0, .nb_pids = 0,
2638 .pids = {0}, .duration = 0, .size = 0, .nb_packets = 0 };
Wentao MA96f68962022-06-15 19:45:35 +08002639 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 +08002640 error = dvr_segment_get_info(location, p_ids[i], &info);
2641 if (!error) {
2642 p_info->size += info.size;
2643 p_info->time += info.duration;
2644 p_info->pkts += info.nb_packets;
2645 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002646 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chen8aed9582021-12-24 17:59:56 +08002647 break;
2648 }
2649 }
hualing chenb9a02922021-12-14 11:29:47 +08002650 continue;
2651 }
2652
2653 if (!error) {
2654 p_info->size += seg_info->size;
2655 p_info->time += seg_info->duration;
2656 p_info->pkts += seg_info->nb_packets;
2657 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002658 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chenb9a02922021-12-14 11:29:47 +08002659 break;
2660 }
2661 }
2662 //free list
2663 DVR_RecordSegmentInfo_t *segment = NULL;
2664 DVR_RecordSegmentInfo_t *segment_tmp = NULL;
2665 list_for_each_entry_safe(segment, segment_tmp, &info_list, head)
2666 {
2667 if (segment) {
2668 list_del(&segment->head);
2669 free(segment);
2670 }
2671 }
2672 }
2673 free(p_ids);
Zhiqiang Hanb9785922021-11-26 18:47:39 +08002674 } else {
2675 n_ids = 0;
Zhiqiang Han620b9252021-11-09 14:23:20 +08002676 }
Wentao MA96f68962022-06-15 19:45:35 +08002677 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 +08002678
2679 return (error)? DVR_FAILURE : DVR_SUCCESS;
2680}
2681
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002682static DVR_Result_t wrapper_record_event_handler(DVR_RecordEvent_t event, void *params, void *userdata)
2683{
wentao.maa210e5e2022-10-12 16:10:03 +08002684 DVR_WrapperEventCtx_t evt = {
2685 .sn = (unsigned long)userdata,
2686 .type = W_REC,
2687 .record.event = event,
2688 .record.status = *(DVR_RecordStatus_t *)params
2689 };
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002690
2691 DVR_RETURN_IF_FALSE(userdata);
2692
Wentao MA804bab12022-11-29 10:01:26 +08002693 DVR_WRAPPER_DEBUG("record event 0x%x (sn:%ld)", evt.record.event, evt.sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002694 return ctx_addRecordEvent(&evt);
2695}
2696
2697static DVR_Result_t wrapper_playback_event_handler(DVR_PlaybackEvent_t event, void *params, void *userdata)
2698{
wentao.maa210e5e2022-10-12 16:10:03 +08002699 DVR_WrapperEventCtx_t evt = {
2700 .sn = (unsigned long)userdata,
2701 .type = W_PLAYBACK,
2702 .playback.event = event,
2703 .playback.status = *(DVR_Play_Notify_t *)params
2704 };
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002705
2706 DVR_RETURN_IF_FALSE(userdata);
2707
2708 evt.sn = (unsigned long)userdata;
2709 evt.type = W_PLAYBACK;
2710 evt.playback.event = event;
2711 evt.playback.status = *(DVR_Play_Notify_t *)params;
Wentao MA804bab12022-11-29 10:01:26 +08002712 DVR_WRAPPER_DEBUG("playback event 0x%x (sn:%ld)", evt.playback.event, evt.sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002713 return ctx_addPlaybackEvent(&evt);
2714}
2715
2716static inline int process_notifyRecord(DVR_WrapperCtx_t *ctx, DVR_RecordEvent_t evt, DVR_WrapperRecordStatus_t *status)
2717{
Wentao MA270dc0f2022-08-23 13:17:26 +08002718 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 +08002719 ctx->sn,
2720 evt,
2721 status->info.time,
2722 status->info.size,
2723 status->info.pkts,
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002724 status->info_obsolete.time,
2725 status->info_obsolete.size,
2726 status->info_obsolete.pkts);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002727
2728 if (ctx->record.event_fn)
2729 return ctx->record.event_fn(evt, status, ctx->record.event_userdata);
2730 return 0;
2731}
2732
Zhiqiang Han620b9252021-11-09 14:23:20 +08002733static int wrapper_saveRecordStatistics(const char *location, DVR_WrapperRecordStatus_t *p_status)
2734{
2735 FILE *fp;
2736 char fpath[DVR_MAX_LOCATION_SIZE];
2737
2738 DVR_RETURN_IF_FALSE(location);
2739 DVR_RETURN_IF_FALSE(p_status);
2740
2741 sprintf(fpath, "%s.stats", location);
2742
2743 /*stats file*/
2744 if ((fp = fopen(fpath, "w"))) {
2745 char buf[256];
2746 snprintf(buf, sizeof(buf), ":%llu:%lu:%u\n",
2747 p_status->info.size - p_status->info_obsolete.size,
2748 p_status->info.time - p_status->info_obsolete.time,
2749 p_status->info.pkts - p_status->info_obsolete.pkts);
2750 fputs(buf, fp);
Zhiqiang Handc3bfe52022-07-07 10:48:39 +08002751 fflush(fp);
2752 fsync(fileno(fp));
Zhiqiang Han620b9252021-11-09 14:23:20 +08002753 fclose(fp);
2754 return DVR_SUCCESS;
2755 }
2756
2757 return DVR_FAILURE;
2758}
2759
2760
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002761static inline int record_startNextSegment(DVR_WrapperCtx_t *ctx)
2762{
2763 DVR_RecordStartParams_t param;
2764 DVR_RecordSegmentInfo_t seg_info;
2765 int i;
2766 int error;
2767
2768 memcpy(&param, &ctx->record.param_update, sizeof(param));
2769 memset(&ctx->record.param_update.segment, 0, sizeof(ctx->record.param_update.segment));
2770 ctx->record.param_update.segment.segment_id = ctx->record.next_segment_id++;
2771 for (i = 0; i < param.segment.nb_pids; i++) {
2772 if (param.segment.pid_action[i] != DVR_RECORD_PID_CLOSE) {
2773 ctx->record.param_update.segment.pids[ctx->record.param_update.segment.nb_pids] = param.segment.pids[i];
2774 ctx->record.param_update.segment.pid_action[ctx->record.param_update.segment.nb_pids] = DVR_RECORD_PID_KEEP;
2775 ctx->record.param_update.segment.nb_pids++;
2776 }
2777 }
2778 error = dvr_record_next_segment(ctx->record.recorder, &ctx->record.param_update, &seg_info);
2779 {
2780 DVR_RecordSegmentInfo_t new_seg_info =
2781 { .id = ctx->record.param_update.segment.segment_id, };
2782 wrapper_updateRecordSegment(ctx, &seg_info, U_ALL);
2783 wrapper_addRecordSegment(ctx, &new_seg_info);
2784 }
2785
Wentao MA96f68962022-06-15 19:45:35 +08002786 DVR_WRAPPER_INFO("record next segment(%llu)=(%d)\n", ctx->record.param_update.segment.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002787 return error;
2788}
2789
Wentao MA270dc0f2022-08-23 13:17:26 +08002790static inline int record_removeSegment(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordSegmentInfo_t *p_seg)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002791{
Wentao MA270dc0f2022-08-23 13:17:26 +08002792 return wrapper_removeRecordSegment(ctx, p_seg);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002793}
2794
2795/*should run periodically to update the current status*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002796static int process_generateRecordStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordStatus_t *status)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002797{
2798 /*the current seg is not covered in the statistics*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002799 DVR_WrapperRecordSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002800
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002801 /*re-calculate the all segments*/
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002802 memset(&ctx->record.status, 0, sizeof(ctx->record.status));
2803
2804 ctx->record.status.state = ctx->record.seg_status.state;
2805 ctx->record.status.pids.nb_pids = ctx->record.seg_status.info.nb_pids;
2806 memcpy(ctx->record.status.pids.pids,
2807 ctx->record.seg_status.info.pids,
2808 sizeof(ctx->record.status.pids.pids));
2809 ctx->current_segment_id = ctx->record.seg_status.info.id;
2810
wentao.mafd5283f2022-10-14 09:51:13 +08002811 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08002812 // prefetch() here incurring self_assign is used to avoid some compiling
2813 // warnings.
2814 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08002815 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
2816 if (p_seg->info.id != ctx->record.seg_status.info.id) {
2817 ctx->record.status.info.time += p_seg->info.duration;
2818 ctx->record.status.info.size += p_seg->info.size;
2819 ctx->record.status.info.pkts += p_seg->info.nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002820 }
2821 }
2822
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002823 ctx->record.status.info_obsolete = ctx->record.obsolete;
2824
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002825 wrapper_updateRecordSegment(ctx, &ctx->record.seg_status.info, U_ALL);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002826
2827 if (status) {
2828 *status = ctx->record.status;
2829 status->info.time += ctx->record.seg_status.info.duration;
2830 status->info.size += ctx->record.seg_status.info.size;
2831 status->info.pkts += ctx->record.seg_status.info.nb_packets;
2832 }
2833
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002834 return DVR_SUCCESS;
2835}
2836
2837
2838static int process_handleRecordEvent(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
2839{
2840 DVR_WrapperRecordStatus_t status;
2841
2842 memset(&status, 0, sizeof(status));
2843
Wentao MA804bab12022-11-29 10:01:26 +08002844 DVR_WRAPPER_DEBUG("evt (sn:%ld) 0x%x (state:%d)\n",
2845 evt->sn, evt->record.event, evt->record.status.state);
hualing chend3b55ab2021-05-06 09:56:27 +08002846 if (ctx->record.param_update.segment.segment_id != evt->record.status.info.id) {
Wentao MA96f68962022-06-15 19:45:35 +08002847 DVR_WRAPPER_INFO("evt (sn:%ld) cur id:0x%x (event id:%d)\n",
Gong Ke2a0ebbe2021-05-25 15:22:50 +08002848 evt->sn, (int)ctx->record.param_update.segment.segment_id, (int)evt->record.status.info.id);
hualing chend3b55ab2021-05-06 09:56:27 +08002849 return 0;
2850 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002851 switch (evt->record.event)
2852 {
2853 case DVR_RECORD_EVENT_STATUS:
2854 {
2855 switch (evt->record.status.state)
2856 {
2857 case DVR_RECORD_STATE_OPENED:
2858 case DVR_RECORD_STATE_CLOSED:
2859 {
2860 ctx->record.seg_status = evt->record.status;
2861
2862 status.state = evt->record.status.state;
2863 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002864 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002865 } break;
2866 case DVR_RECORD_STATE_STARTED:
2867 {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002868 ctx->record.seg_status = evt->record.status;
2869
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002870 process_generateRecordStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002871 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002872 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002873
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002874 /*restart to next segment*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002875 if (ctx->record.param_open.segment_size
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002876 && evt->record.status.info.size >= ctx->record.param_open.segment_size) {
Wentao MA96f68962022-06-15 19:45:35 +08002877 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 +08002878 ctx->sn,
2879 evt->record.status.info.size,
2880 ctx->record.param_open.segment_size);
Zhiqiang Hand977e972020-05-11 11:30:47 +08002881 if (record_startNextSegment(ctx) != DVR_SUCCESS) {
2882 /*should notify the recording's stop*/
2883 int error = dvr_record_close(ctx->record.recorder);
Wentao MA96f68962022-06-15 19:45:35 +08002884 DVR_WRAPPER_INFO("stop record(%lu)=%d, failed to start new segment for recording.",
Zhiqiang Hand977e972020-05-11 11:30:47 +08002885 ctx->sn, error);
2886 status.state = DVR_RECORD_STATE_CLOSED;
2887 process_notifyRecord(ctx, DVR_RECORD_EVENT_WRITE_ERROR, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002888 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Hand977e972020-05-11 11:30:47 +08002889 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002890 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002891
2892 if (ctx->record.param_open.is_timeshift
2893 && ctx->record.param_open.max_time
2894 && status.info.time >= ctx->record.param_open.max_time) {
Wentao MA270dc0f2022-08-23 13:17:26 +08002895 DVR_WrapperRecordSegmentInfo_t *p_seg;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002896
2897 /*as the player do not support null playlist,
2898 there must be one segment existed at any time,
2899 we have to keep two segments before remove one*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002900 p_seg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
2901 if (p_seg == list_first_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head)) {
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002902 /*only one segment, waiting for more*/
Wentao MA96f68962022-06-15 19:45:35 +08002903 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 +08002904 status.info.size,
2905 ctx->record.param_open.max_time,
2906 ctx->record.param_open.segment_size);
2907 } else {
2908 /*timeshifting, remove the 1st segment and notify the player*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002909 record_removeSegment(ctx, p_seg);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002910
2911 process_generateRecordStatus(ctx, &status);
2912 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002913 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002914 }
2915 }
2916
Wentao MAf4072032022-06-30 13:50:45 +08002917 const loff_t actual_size = status.info.size;
2918 const loff_t max_size = ctx->record.param_open.max_size;
2919 const loff_t segment_size = ctx->record.param_open.segment_size;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002920
Wentao MAf4072032022-06-30 13:50:45 +08002921 if (ctx->record.param_open.is_timeshift && max_size) {
2922 if (actual_size >= max_size) {
Wentao MA270dc0f2022-08-23 13:17:26 +08002923 DVR_WrapperRecordSegmentInfo_t *p_seg;
Wentao MAf4072032022-06-30 13:50:45 +08002924 /*as the player do not support null playlist,
2925 there must be one segment existed at any time,
2926 we have to keep two segments before remove one*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002927 p_seg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
2928 if (p_seg == list_first_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head)) {
Wentao MAf4072032022-06-30 13:50:45 +08002929 /*only one segment, waiting for more*/
2930 DVR_WRAPPER_INFO("warning: the size(%lld) of record < max size of segment(%lld)\n",
2931 actual_size, segment_size);
2932 } else {
Wentao MA270dc0f2022-08-23 13:17:26 +08002933 record_removeSegment(ctx, p_seg);
Wentao MAf4072032022-06-30 13:50:45 +08002934
2935 process_generateRecordStatus(ctx, &status);
2936 process_notifyRecord(ctx, evt->record.event, &status);
2937 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
2938 }
2939 if (actual_size >= max_size + segment_size/2) {
2940 dvr_record_discard_coming_data(ctx->record.recorder,DVR_TRUE);
2941 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002942 } else {
Wentao MAf4072032022-06-30 13:50:45 +08002943 dvr_record_discard_coming_data(ctx->record.recorder,DVR_FALSE);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002944 }
2945 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002946 } break;
2947 case DVR_RECORD_STATE_STOPPED:
2948 {
2949 ctx->record.seg_status = evt->record.status;
2950
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002951 process_generateRecordStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002952 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002953 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002954 } break;
2955 default:
2956 break;
2957 }
2958 } break;
hualing chen4b7c15d2020-04-07 16:13:48 +08002959 case DVR_RECORD_EVENT_WRITE_ERROR: {
2960 ctx->record.seg_status = evt->record.status;
2961 status.state = evt->record.status.state;
2962 process_notifyRecord(ctx, evt->record.event, &status);
2963 }break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002964 default:
2965 break;
2966 }
2967 return DVR_SUCCESS;
2968}
2969
2970static inline int process_notifyPlayback(DVR_WrapperCtx_t *ctx, DVR_PlaybackEvent_t evt, DVR_WrapperPlaybackStatus_t *status)
2971{
Wentao MA80179512022-11-03 12:20:03 +08002972 DVR_RETURN_IF_FALSE(ctx->playback.event_fn != NULL);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002973
Wentao MA80179512022-11-03 12:20:03 +08002974 const time_t cur_time = status->info_cur.time;
2975 const time_t full_time = status->info_full.time;
2976 const time_t obsolete_time = status->info_obsolete.time;
2977 const time_t origin_offset = cur_time + obsolete_time;
2978 DVR_WRAPPER_INFO("playback progress notify(sn:%ld) evt(0x%x)"
2979 " actual_slider_pos: %02d:%02d:%02d.%03d/%02d:%02d:%02d.%03d (%7ld ms/%7ld ms),"
2980 " offset_from_origin: %02d:%02d:%02d.%03d (%7ld ms),"
2981 " dump status:state/cur/full/obsolete(%d/%ld/%ld/%ld)",
2982 ctx->sn,evt,cur_time/1000/3600,cur_time/1000%3600/60,cur_time/1000%60,cur_time%1000,
2983 full_time/1000/3600,full_time/1000%3600/60,full_time/1000%60,full_time%1000,
2984 cur_time,full_time,
2985 origin_offset/1000/3600,origin_offset/1000%3600/60,origin_offset/1000%60,origin_offset%1000,
2986 origin_offset,status->state,cur_time,full_time,obsolete_time);
2987
2988 return ctx->playback.event_fn(evt, status, ctx->playback.event_userdata);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002989}
2990
2991/*should run periodically to update the current status*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002992static int process_generatePlaybackStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperPlaybackStatus_t *status)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002993{
2994 /*the current seg is not covered in the statistics*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002995 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002996
2997 memset(&ctx->playback.status, 0, sizeof(ctx->playback.status));
2998 ctx->playback.status.pids = ctx->playback.pids_req;
2999
3000 ctx->playback.status.state = ctx->playback.seg_status.state;
3001 ctx->playback.status.speed = ctx->playback.seg_status.speed;
3002 ctx->playback.status.flags = ctx->playback.seg_status.flags;
3003 ctx->current_segment_id = ctx->playback.seg_status.segment_id;
3004
wentao.mafd5283f2022-10-14 09:51:13 +08003005 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08003006 // prefetch() here incurring self_assign is used to avoid some compiling
3007 // warnings.
3008 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08003009 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
3010 if (p_seg->seg_info.id == ctx->playback.seg_status.segment_id) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003011 break;
hualing chen451c8f72022-03-09 13:05:52 +08003012 }
3013
Wentao MA270dc0f2022-08-23 13:17:26 +08003014 ctx->playback.status.info_cur.time += p_seg->seg_info.duration;
3015 ctx->playback.status.info_cur.size += p_seg->seg_info.size;
3016 ctx->playback.status.info_cur.pkts += p_seg->seg_info.nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003017 }
wentao.mafd5283f2022-10-14 09:51:13 +08003018 // This error is suppressed as the macro code is picked from kernel.
wentao.maa22bc852022-10-13 12:18:06 +08003019 // prefetch() here incurring self_assign is used to avoid some compiling
3020 // warnings.
3021 // coverity[self_assign]
Wentao MA270dc0f2022-08-23 13:17:26 +08003022 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
3023 ctx->playback.status.info_full.time += p_seg->seg_info.duration;
3024 ctx->playback.status.info_full.size += p_seg->seg_info.size;
3025 ctx->playback.status.info_full.pkts += p_seg->seg_info.nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003026 }
3027
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08003028 if (status) {
3029 *status = ctx->playback.status;
3030 /*deal with current, lack size and pkts with the current*/
3031 status->info_cur.time += ctx->playback.seg_status.time_cur;
hualing chen56c0a162022-01-27 17:01:50 +08003032 //get last segment id
Wentao MA270dc0f2022-08-23 13:17:26 +08003033 DVR_WrapperRecordSegmentInfo_t *p_seg;
hualing chen56c0a162022-01-27 17:01:50 +08003034
Wentao MA270dc0f2022-08-23 13:17:26 +08003035 p_seg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
3036 if (ctx->playback.tf_full == DVR_TRUE && p_seg->info.id == ctx->current_segment_id) {
hualing chen56c0a162022-01-27 17:01:50 +08003037 status->disguised_info_obsolete.time = ctx->playback.obsolete.time + ctx->playback.seg_status.time_cur;
3038 status->info_obsolete.time = ctx->playback.obsolete.time;
Wentao MA270dc0f2022-08-23 13:17:26 +08003039 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 +08003040 }
3041 else
3042 {
Wentao MA804bab12022-11-29 10:01:26 +08003043 status->info_obsolete.time = ctx->playback.obsolete.time;
3044 status->disguised_info_obsolete.time = ctx->playback.obsolete.time;
hualing chen56c0a162022-01-27 17:01:50 +08003045 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08003046 }
3047
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003048 return DVR_SUCCESS;
3049}
3050
3051static int process_handlePlaybackEvent(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
3052{
Wentao MA804bab12022-11-29 10:01:26 +08003053 DVR_WRAPPER_DEBUG("evt (sn:%ld) 0x%x (state:%d) cur(%lld:%u/%u)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003054 evt->sn, evt->playback.event,
3055 evt->playback.status.play_status.state,
3056 evt->playback.status.play_status.segment_id,
3057 evt->playback.status.play_status.time_cur,
3058 evt->playback.status.play_status.time_end);
3059
3060 /*evt PLAYTIME will break the last logic, do not save*/
hualing chene3797f02021-01-13 14:53:28 +08003061 if (evt->playback.event != DVR_PLAYBACK_EVENT_NOTIFY_PLAYTIME
3062 && evt->playback.event != DVR_PLAYBACK_EVENT_NODATA
3063 && evt->playback.event != DVR_PLAYBACK_EVENT_DATARESUME
3064 )
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003065 ctx->playback.last_event = evt->playback.event;
3066
3067 switch (evt->playback.event)
3068 {
3069 case DVR_PLAYBACK_EVENT_FIRST_FRAME:
3070 case DVR_PLAYBACK_EVENT_REACHED_END:
3071 case DVR_PLAYBACK_EVENT_TRANSITION_OK:
3072 case DVR_PLAYBACK_EVENT_NOTIFY_PLAYTIME:
hualing chenb5cd42e2020-04-15 17:03:34 +08003073 case DVR_PLAYBACK_EVENT_ERROR:
hualing chenf291cf32020-06-18 10:50:30 +08003074 case DVR_PLAYBACK_EVENT_REACHED_BEGIN:
hualing chene3797f02021-01-13 14:53:28 +08003075 case DVR_PLAYBACK_EVENT_NODATA:
3076 case DVR_PLAYBACK_EVENT_DATARESUME:
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003077 {
3078 DVR_WrapperPlaybackStatus_t status;
3079
3080 /*copy status of segment*/
3081 ctx->playback.seg_status = evt->playback.status.play_status;
3082
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08003083 /*generate status of the whole playback*/
3084 process_generatePlaybackStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003085
3086 if (evt->playback.event == DVR_PLAYBACK_EVENT_REACHED_END) {
Wentao MA96f68962022-06-15 19:45:35 +08003087 DVR_WRAPPER_INFO("playback(sn:%ld) event:0x%x\n", evt->sn, evt->playback.event);
hualing chenb9b358a2021-08-17 15:06:36 +08003088 if (ctx->playback.param_open.is_timeshift
3089 || ctx_isPlay_recording(ctx->playback.param_open.location)) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003090 /*wait for more data in recording*/
Zhiqiang Han31846002021-11-04 10:49:06 +08003091 }
3092 /*trust the low level, make NO check.
3093 As this evt is changed to only once due to some operations(paused) in low level.
3094 else if ((status.info_cur.time + DVR_PLAYBACK_END_GAP) >= ctx->playback.status.info_full.time) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003095 process_notifyPlayback(ctx, evt->playback.event, &status);
Zhiqiang Han31846002021-11-04 10:49:06 +08003096 }
3097 */
3098 else {
3099 process_notifyPlayback(ctx, evt->playback.event, &status);
hualing chenb5cd42e2020-04-15 17:03:34 +08003100 ctx->playback.reach_end = DVR_TRUE;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003101 }
hualing chenf291cf32020-06-18 10:50:30 +08003102 } else if (evt->playback.event != DVR_PLAYBACK_EVENT_REACHED_BEGIN) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003103 process_notifyPlayback(ctx, evt->playback.event, &status);
3104 }
3105 } break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003106 case DVR_PLAYBACK_EVENT_TRANSITION_FAILED:
3107 case DVR_PLAYBACK_EVENT_KEY_FAILURE:
3108 case DVR_PLAYBACK_EVENT_NO_KEY:
3109 {
Wentao MA96f68962022-06-15 19:45:35 +08003110 DVR_WRAPPER_INFO("playback(sn:%ld) error event:0x%x\n", evt->sn, evt->playback.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003111 } break;
3112 default:
3113 {
Wentao MA96f68962022-06-15 19:45:35 +08003114 DVR_WRAPPER_INFO("playback(sn:%ld) unknown event:0x%x\n", evt->sn, evt->playback.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003115 } break;
3116 }
3117 return 0;
3118}
3119
3120static inline int process_handleEvents(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
3121{
3122 return (evt->type == W_REC)? process_handleRecordEvent(evt, ctx) : process_handlePlaybackEvent(evt, ctx);
3123}
3124
Wentao MA96f68962022-06-15 19:45:35 +08003125int dvr_wrapper_set_log_level (int level)
3126{
Wentao MA804bab12022-11-29 10:01:26 +08003127 DVR_WRAPPER_INFO("libdvr_api, set_log_level %d", level);
Wentao MA96f68962022-06-15 19:45:35 +08003128 if (level<LOG_LV_DEFAULT || level>LOG_LV_FATAL) {
3129 DVR_WRAPPER_ERROR("Invalid dvr log level:%d", g_dvr_log_level);
3130 return DVR_FAILURE;
3131 }
3132 g_dvr_log_level = level;
3133 DVR_WRAPPER_INFO("New dvr log level:%d", g_dvr_log_level);
3134 return DVR_SUCCESS;
3135}
3136
Wentao MA5629ad82022-08-24 10:03:02 +08003137int dvr_wrapper_set_ac4_preselection_id(DVR_WrapperPlayback_t playback, int presel_id)
3138{
3139 DVR_WrapperCtx_t *ctx;
3140 int error;
3141
3142 DVR_RETURN_IF_FALSE(playback==NULL);
3143
3144 ctx = ctx_getPlayback((unsigned long)playback);
3145 DVR_RETURN_IF_FALSE(ctx);
3146
3147 wrapper_mutex_lock(&ctx->wrapper_lock);
3148
3149 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
3150
Wentao MA804bab12022-11-29 10:01:26 +08003151 DVR_WRAPPER_INFO("libdvr_api, set_ac4_preselection_id %d", presel_id);
Wentao MA5629ad82022-08-24 10:03:02 +08003152 error = dvr_playback_set_ac4_preselection_id(ctx->playback.player, presel_id);
3153
3154 wrapper_mutex_unlock(&ctx->wrapper_lock);
3155
3156 return error;
3157}
3158
wentao ma7d642782022-10-23 18:26:16 -07003159int dvr_wrapper_property_set(const char* prop_name, const char* prop_value)
3160{
3161 return dvr_prop_write(prop_name,prop_value);
3162}
3163
3164int dvr_wrapper_property_get(const char* prop_name, char* prop_value, int length)
3165{
3166 return dvr_prop_read(prop_name,prop_value,length);
3167}
3168