blob: 5315082f4ce6ad36451dd2ffb2f18931dbe292b7 [file] [log] [blame]
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001#include <stddef.h>
Zhiqiang Han620b9252021-11-09 14:23:20 +08002#include <unistd.h>
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003#include <stdlib.h>
4#include <pthread.h>
5#include <string.h>
6#include <time.h>
7#include <errno.h>
Zhiqiang Han18f42c82021-08-11 17:13:28 +08008#include <sys/time.h>
9#include <time.h>
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080010
11#include "dvr_types.h"
12#include "dvr_record.h"
13#include "dvr_crypto.h"
14#include "dvr_playback.h"
15#include "dvr_segment.h"
16
17#include "AmTsPlayer.h"
18
19#include "list.h"
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080020
21#include "dvr_wrapper.h"
22
Wentao MA96f68962022-06-15 19:45:35 +080023#define WRAPPER_LOG_TAG "libdvr-wrapper"
24#define DVR_WRAPPER_DEBUG(...) DVR_LOG_PRINT(LOG_LV_DEBUG, WRAPPER_LOG_TAG, __VA_ARGS__)
25#define DVR_WRAPPER_INFO(...) DVR_LOG_PRINT(LOG_LV_INFO, WRAPPER_LOG_TAG, __VA_ARGS__)
26#define DVR_WRAPPER_WARN(...) DVR_LOG_PRINT(LOG_LV_WARN, WRAPPER_LOG_TAG, __VA_ARGS__)
27#define DVR_WRAPPER_ERROR(...) DVR_LOG_PRINT(LOG_LV_ERROR, WRAPPER_LOG_TAG, __VA_ARGS__)
28#define DVR_WRAPPER_FATAL(...) DVR_LOG_PRINT(LOG_LV_FATAL, WRAPPER_LOG_TAG, __VA_ARGS__)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080029
30/*duration of data to resume if paused with EVT_REACHED_END in timeshifting*/
hualing chen2932d372020-04-29 13:44:00 +080031#define TIMESHIFT_DATA_DURATION_TO_RESUME (600)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080032/*a tolerant gap*/
33#define DVR_PLAYBACK_END_GAP (1000)
34
Wentao MA96f68962022-06-15 19:45:35 +080035int g_dvr_log_level = LOG_LV_DEFAULT;
36
Zhiqiang Han2d8cd822020-03-16 13:58:10 +080037enum {
38 W_REC = 1,
39 W_PLAYBACK = 2,
40};
41
42enum {
43 U_PIDS = 0x01,
44 U_STAT = 0x02,
45 U_ALL = U_PIDS | U_STAT,
46};
47
48typedef struct {
Gong Kefdb31922022-06-17 17:11:16 +080049 pthread_mutex_t lock;
50 pthread_cond_t cond;
51 int inited;
52 int locked;
53} DVR_WrapperMutex_t;
54
55static void
56wrapper_mutex_init (DVR_WrapperMutex_t *lock)
57{
58 pthread_condattr_t cattr;
59
Zhiqiang Han2259da32022-07-07 15:52:58 +080060 if (lock->inited)
Gong Kefdb31922022-06-17 17:11:16 +080061 return;
62
63 pthread_mutex_init(&lock->lock, NULL);
64
65 pthread_condattr_init(&cattr);
66 pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
67 pthread_cond_init(&lock->cond, &cattr);
68 pthread_condattr_destroy(&cattr);
69
70 lock->locked = 0;
71 lock->inited = 1;
72}
73
74static int
75wrapper_mutex_lock (DVR_WrapperMutex_t *lock)
76{
77 pthread_mutex_lock(&lock->lock);
78 while (lock->locked) {
79 pthread_cond_wait(&lock->cond, &lock->lock);
80 }
81 lock->locked = 1;
82 pthread_mutex_unlock(&lock->lock);
83
84 return 0;
85}
86
87static int
88wrapper_mutex_unlock (DVR_WrapperMutex_t *lock)
89{
90 pthread_mutex_lock(&lock->lock);
91 lock->locked = 0;
92 pthread_mutex_unlock(&lock->lock);
93 pthread_cond_signal(&lock->cond);
94
95 return 0;
96}
97
98static int
99wrapper_mutex_timedlock (DVR_WrapperMutex_t *lock, struct timespec *tv)
100{
101 int r = 0;
102
103 pthread_mutex_lock(&lock->lock);
104 if (lock->locked) {
Zhiqiang Han61ceb3a2022-07-04 17:03:52 +0800105 //DVR_WRAPPER_DEBUG("Enter cond_timedwait");
Gong Kefdb31922022-06-17 17:11:16 +0800106 r = pthread_cond_timedwait(&lock->cond, &lock->lock, tv);
Zhiqiang Han61ceb3a2022-07-04 17:03:52 +0800107 //DVR_WRAPPER_DEBUG("Leave cond_timedwait");
Gong Kefdb31922022-06-17 17:11:16 +0800108 }
109 if (r == 0) {
110 if (!lock->locked) {
111 lock->locked = 1;
112 } else {
113 r = ETIMEDOUT;
114 }
115 }
116 pthread_mutex_unlock(&lock->lock);
117
118 return r;
119}
120
121#define WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(expr, lock)\
122 do {\
123 if (!(expr)) {\
124 DVR_INFO("%s-%d failed", __func__, __LINE__);\
125 wrapper_mutex_unlock(lock);\
126 return DVR_FAILURE;\
127 }\
128 } while (0);
129
130
131typedef struct {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800132 /*make lock the 1st item in the structure*/
Gong Kefdb31922022-06-17 17:11:16 +0800133 DVR_WrapperMutex_t wrapper_lock;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800134
135 /*rec or play*/
136 int type;
137
138 /*valid if (sn != 0)*/
139 unsigned long sn;
140 unsigned long sn_linked;
141
142 struct list_head segments; /**<head-add list*/
143 uint64_t current_segment_id; /**<id of the current segment*/
144
145 union {
146 struct {
147 DVR_WrapperRecordOpenParams_t param_open;
148 DVR_RecordStartParams_t param_start;
149 DVR_RecordStartParams_t param_update;
150 DVR_RecordHandle_t recorder;
151 DVR_RecordEventFunction_t event_fn;
152 void *event_userdata;
153
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800154 /*total status = seg_status + status + obsolete*/
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800155 DVR_RecordStatus_t seg_status; /**<status of current segment*/
156 DVR_WrapperRecordStatus_t status; /**<status of remaining segments*/
157 uint64_t next_segment_id;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800158
159 DVR_WrapperInfo_t obsolete; /**<data obsolete due to the max limit*/
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800160 } record;
161
162 struct {
163 DVR_WrapperPlaybackOpenParams_t param_open;
164 DVR_PlaybackHandle_t player;
165 DVR_PlaybackEventFunction_t event_fn;
166 void *event_userdata;
167
168 /*total status = seg_status + status*/
169 DVR_PlaybackStatus_t seg_status;
170 DVR_WrapperPlaybackStatus_t status;
171 DVR_PlaybackPids_t pids_req;
172 DVR_PlaybackEvent_t last_event;
Zhiqiang Han3eb75f92020-04-08 10:07:55 +0800173 float speed;
hualing chenb5cd42e2020-04-15 17:03:34 +0800174 DVR_Bool_t reach_end;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800175
176 DVR_WrapperInfo_t obsolete;
hualing chen56c0a162022-01-27 17:01:50 +0800177 DVR_Bool_t tf_full;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800178 } playback;
179 };
180} DVR_WrapperCtx_t;
181
182typedef struct {
183 struct list_head head;
184 unsigned long sn;
185
186 /* rec or playback */
187 int type;
188
189 union {
190 struct {
191 DVR_RecordEvent_t event;
192 DVR_RecordStatus_t status;
193 } record;
194 struct {
195 DVR_PlaybackEvent_t event;
196 DVR_Play_Notify_t status;
197 } playback;
198 };
199} DVR_WrapperEventCtx_t;
200
201typedef struct {
202 pthread_mutex_t lock;
203 char *name;
204 int running;
205 pthread_cond_t cond;
206 pthread_t thread;
207 int type;
208} DVR_WrapperThreadCtx_t;
209
210typedef struct {
211 struct list_head head;
212
213 DVR_RecordSegmentInfo_t seg_info;
214 DVR_PlaybackSegmentInfo_t playback_info;
215} DVR_WrapperPlaybackSegmentInfo_t;
216
217typedef struct {
218 struct list_head head;
219
220 DVR_RecordSegmentInfo_t info;
221} DVR_WrapperRecordSegmentInfo_t;
222
223/* serial num generater */
224static unsigned long sn = 1;
225static pthread_mutex_t sn_lock = PTHREAD_MUTEX_INITIALIZER;
226
227static inline unsigned long get_sn()
228{
hualing chenab0d1262021-09-26 15:22:50 +0800229 unsigned long no = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800230
231 pthread_mutex_lock(&sn_lock);
232 no = sn++;
233 if (!no)
234 no = sn++;
235 pthread_mutex_unlock(&sn_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800236 return no;
237}
238
239/* entity ctx */
240#define DVR_WRAPPER_MAX 10
241
242static DVR_WrapperCtx_t record_list[DVR_WRAPPER_MAX] =
243{
244 [0 ... (DVR_WRAPPER_MAX - 1)] =
245 {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800246 .type = W_REC,
247 }
248};
249
250static DVR_WrapperCtx_t playback_list[DVR_WRAPPER_MAX] =
251{
252 [0 ... (DVR_WRAPPER_MAX - 1)] =
253 {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800254 .type = W_PLAYBACK,
255 }
256};
257
258/* events lists */
259static struct list_head record_evt_list = LIST_HEAD_INIT(record_evt_list);
260static struct list_head playback_evt_list = LIST_HEAD_INIT(playback_evt_list);
261
262static pthread_mutex_t record_evt_list_lock = PTHREAD_MUTEX_INITIALIZER;
263static pthread_mutex_t playback_evt_list_lock = PTHREAD_MUTEX_INITIALIZER;
264
265static DVR_WrapperThreadCtx_t wrapper_thread[2] =
266{
267 [0] =
268 {
269 .lock = PTHREAD_MUTEX_INITIALIZER,
270 .running = 0,
271 .name = "record",
272 .type = W_REC,
273 },
274 [1] =
275 {
276 .lock = PTHREAD_MUTEX_INITIALIZER,
277 .running = 0,
278 .name = "playback",
279 .type = W_PLAYBACK,
280 },
281};
282
283/*now only support one timeshift now*/
284static unsigned long sn_timeshift_record;
285static unsigned long sn_timeshift_playback;
286
287static void *wrapper_task(void *arg);
288static inline int process_handleEvents(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx);
289
290static DVR_Result_t wrapper_record_event_handler(DVR_RecordEvent_t event, void *params, void *userdata);
291static DVR_Result_t wrapper_playback_event_handler(DVR_PlaybackEvent_t event, void *params, void *userdata);
292
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800293static int process_generateRecordStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordStatus_t *status);
294static int process_generatePlaybackStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperPlaybackStatus_t *status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800295
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800296static int get_timespec_timeout(int timeout, struct timespec *ts)
297{
298 struct timespec ots;
299 int left, diff;
300
301 clock_gettime(CLOCK_MONOTONIC, &ots);
302
303 ts->tv_sec = ots.tv_sec + timeout / 1000;
304 ts->tv_nsec = ots.tv_nsec;
305
306 left = timeout % 1000;
307 left *= 1000000;
308 diff = 1000000000 - ots.tv_nsec;
309
310 if (diff <= left) {
311 ts->tv_sec++;
312 ts->tv_nsec = left-diff;
313 } else {
314 ts->tv_nsec += left;
315 }
316
317 return 0;
318}
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800319
320static DVR_WrapperEventCtx_t *ctx_getEvent(struct list_head *list, pthread_mutex_t *list_lock)
321{
Wentao MA270dc0f2022-08-23 13:17:26 +0800322 DVR_WrapperEventCtx_t *p_evt;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800323
324 pthread_mutex_lock(list_lock);
325 if (list_empty(list))
Wentao MA270dc0f2022-08-23 13:17:26 +0800326 p_evt = NULL;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800327 else {
Wentao MA270dc0f2022-08-23 13:17:26 +0800328 p_evt = list_first_entry(list, DVR_WrapperEventCtx_t, head);
329 list_del(&p_evt->head);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800330 }
331 pthread_mutex_unlock(list_lock);
332
Wentao MA270dc0f2022-08-23 13:17:26 +0800333 return p_evt;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800334}
335
336static inline DVR_WrapperEventCtx_t *ctx_getRecordEvent()
337{
338 return ctx_getEvent(&record_evt_list, &record_evt_list_lock);
339}
340
341static inline DVR_WrapperEventCtx_t *ctx_getPlaybackEvent()
342{
343 return ctx_getEvent(&playback_evt_list, &playback_evt_list_lock);
344}
345
346static int ctx_addEvent(struct list_head *list, pthread_mutex_t *lock, DVR_WrapperEventCtx_t *evt)
347{
348 DVR_WrapperEventCtx_t *padd;
349 padd = (DVR_WrapperEventCtx_t *)calloc(1, sizeof(DVR_WrapperEventCtx_t));
350 DVR_RETURN_IF_FALSE(padd);
351
352 *padd = *evt;
353 pthread_mutex_lock(lock);
354 list_add_tail(&padd->head, list);
355 pthread_mutex_unlock(lock);
356 return DVR_SUCCESS;
357}
358
359static inline void ctx_freeEvent(DVR_WrapperEventCtx_t *evt)
360{
361 free(evt);
362}
363
364/*useless*/
365static void ctx_cleanOutdatedEvents(struct list_head *evt_list,
366 pthread_mutex_t *evt_list_lock,
367 DVR_WrapperCtx_t *list)
368{
Wentao MA270dc0f2022-08-23 13:17:26 +0800369 DVR_WrapperEventCtx_t *p_evt, *p_evt_tmp;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800370 unsigned long sns[DVR_WRAPPER_MAX];
371 int cnt = 0;
372 int i;
373 int found = 0;
374
375 /*copy all valid sns*/
376 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
377 sns[cnt] = list[i].sn;
378 if (!sns[cnt])
379 cnt++;
380 }
381
382 /*free evts that not belong to any valid sns*/
383 pthread_mutex_lock(evt_list_lock);
Wentao MA270dc0f2022-08-23 13:17:26 +0800384 list_for_each_entry_safe(p_evt, p_evt_tmp, evt_list, head) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800385 for (i = 0; i < cnt; i++) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800386 if (p_evt->sn == sns[i]) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800387 found = 1;
388 break;
389 }
390 }
391 if (!found) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800392 list_del(&p_evt->head);
393 ctx_freeEvent(p_evt);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800394 }
395 }
396 pthread_mutex_unlock(evt_list_lock);
397}
398
399static inline void ctx_cleanOutdatedRecordEvents()
400{
401 ctx_cleanOutdatedEvents(&record_evt_list, &record_evt_list_lock, record_list);
402}
403
404static inline void ctx_cleanOutdatedPlaybackEvents()
405{
406 ctx_cleanOutdatedEvents(&playback_evt_list, &playback_evt_list_lock, playback_list);
407}
408
hualing chenb9b358a2021-08-17 15:06:36 +0800409//check this play is recording file
410//return 0 if not the recording
411//else return record id
412static inline int ctx_isPlay_recording(char *play_location)
413{
414 int i;
415 DVR_WrapperCtx_t *cnt;
416
417 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
418 cnt = &record_list[i];
Wentao MA96f68962022-06-15 19:45:35 +0800419 //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 +0800420 if (!strcmp(cnt->record.param_open.location, play_location)) {
Wentao MA96f68962022-06-15 19:45:35 +0800421 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 +0800422 return cnt->sn;
423 }
424 }
Wentao MA270dc0f2022-08-23 13:17:26 +0800425 DVR_WRAPPER_INFO(" not found any play is in recording [%d]", DVR_WRAPPER_MAX);
hualing chenb9b358a2021-08-17 15:06:36 +0800426 return 0;
427}
428//check this record is playing file
429//return 0 if not the playing
430//else return playback id
431static inline int ctx_isRecord_playing(char *rec_location)
432{
433 int i;
434 DVR_WrapperCtx_t *cnt;
435 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
436 cnt = &playback_list[i];
Wentao MA96f68962022-06-15 19:45:35 +0800437 //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 +0800438 if (!strcmp(cnt->playback.param_open.location, rec_location)) {
Wentao MA96f68962022-06-15 19:45:35 +0800439 DVR_WRAPPER_INFO("[%d]sn[%d]P[%s]R[%s] ..found.\n",i, cnt->sn, cnt->playback.param_open.location, rec_location);
hualing chenb9b358a2021-08-17 15:06:36 +0800440 return cnt->sn;
441 }
442 }
Wentao MA96f68962022-06-15 19:45:35 +0800443 DVR_WRAPPER_INFO(" not found rec is playing [%d]", DVR_WRAPPER_MAX);
hualing chenb9b358a2021-08-17 15:06:36 +0800444 return 0;
445}
446
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800447static inline DVR_WrapperCtx_t *ctx_get(unsigned long sn, DVR_WrapperCtx_t *list)
448{
449 int i;
450 for (i = 0; i < DVR_WRAPPER_MAX; i++) {
Gong Kefdb31922022-06-17 17:11:16 +0800451 if (list[i].sn == sn) {
452 wrapper_mutex_init(&list[i].wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800453 return &list[i];
Gong Kefdb31922022-06-17 17:11:16 +0800454 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800455 }
456 return NULL;
457}
458
459static inline void ctx_reset(DVR_WrapperCtx_t *ctx)
460{
461 memset((char *)ctx + offsetof(DVR_WrapperCtx_t, sn),
462 0,
463 sizeof(DVR_WrapperCtx_t) - offsetof(DVR_WrapperCtx_t, sn));
464}
465
466static inline int ctx_valid(DVR_WrapperCtx_t *ctx)
467{
468 return (ctx->sn != 0);
469}
470
471static inline DVR_WrapperCtx_t *ctx_getRecord(unsigned long sn)
472{
473 return ctx_get(sn, record_list);
474}
475
476static inline DVR_WrapperCtx_t *ctx_getPlayback(unsigned long sn)
477{
478 return ctx_get(sn, playback_list);
479}
480
481static int wrapper_requestThread(DVR_WrapperThreadCtx_t *ctx, void *(thread_fn)(void *))
482{
483 pthread_mutex_lock(&ctx->lock);
484 if (ctx->running == 0) {
wentao.maa210e5e2022-10-12 16:10:03 +0800485 pthread_condattr_t attr = {0};
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800486 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
487 pthread_cond_init(&ctx->cond, &attr);
488 pthread_condattr_destroy(&attr);
Wentao MA96f68962022-06-15 19:45:35 +0800489 DVR_WRAPPER_INFO("start wrapper thread(%s) ...\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800490 pthread_create(&ctx->thread, NULL, thread_fn, ctx);
Wentao MA96f68962022-06-15 19:45:35 +0800491 DVR_WRAPPER_INFO("wrapper thread(%s) started\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800492 }
493 ctx->running++;
494 pthread_mutex_unlock(&ctx->lock);
495 return 0;
496}
497
498static int wrapper_releaseThread(DVR_WrapperThreadCtx_t *ctx)
499{
500 pthread_mutex_lock(&ctx->lock);
501 ctx->running--;
502 if (!ctx->running) {
503 pthread_cond_broadcast(&ctx->cond);
504 pthread_mutex_unlock(&ctx->lock);
505
Wentao MA96f68962022-06-15 19:45:35 +0800506 DVR_WRAPPER_INFO("stop wrapper thread(%s) ...\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800507 pthread_join(ctx->thread, NULL);
Wentao MA96f68962022-06-15 19:45:35 +0800508 DVR_WRAPPER_INFO("wrapper thread(%s) stopped\n", ctx->name);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800509
510 pthread_mutex_lock(&ctx->lock);
511 if (!ctx->running) /*protect*/
512 pthread_cond_destroy(&ctx->cond);
513 }
514 pthread_mutex_unlock(&ctx->lock);
515 return 0;
516}
517
518#define WRAPPER_THREAD_RECORD (&wrapper_thread[0])
519#define WRAPPER_THREAD_PLAYBACK (&wrapper_thread[1])
520
521static inline int wrapper_requestThreadFor(DVR_WrapperCtx_t *ctx)
522{
523 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC)?
524 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
525 return wrapper_requestThread(thread_ctx, wrapper_task);
526}
527
528static inline int wrapper_releaseThreadFor(DVR_WrapperCtx_t *ctx)
529{
530 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC)?
531 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
532 return wrapper_releaseThread(thread_ctx);
533}
534
535static inline int wrapper_releaseThreadForType(int type)
536{
537 DVR_WrapperThreadCtx_t *thread_ctx = (type == W_REC)?
538 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
539 return wrapper_releaseThread(thread_ctx);
540}
541
542static inline void wrapper_threadSignal(DVR_WrapperThreadCtx_t *thread_ctx)
543{
544 pthread_cond_signal(&thread_ctx->cond);
545}
546
547static inline int wrapper_threadWait(DVR_WrapperThreadCtx_t *thread_ctx)
548{
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800549 struct timespec rt;
550 get_timespec_timeout(200, &rt);
551 pthread_cond_timedwait(&thread_ctx->cond, &thread_ctx->lock, &rt);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800552 return 0;
553}
554
555static inline void wrapper_threadSignalForType(int type)
556{
557 DVR_WrapperThreadCtx_t *thread_ctx = (type == W_REC) ?
558 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
559 wrapper_threadSignal(thread_ctx);
560}
561
562static inline void wrapper_threadSignalFor(DVR_WrapperCtx_t *ctx)
563{
564 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC) ?
565 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
566 wrapper_threadSignal(thread_ctx);
567}
568
569static inline int wrapper_threadWaitFor(DVR_WrapperCtx_t *ctx)
570{
571 DVR_WrapperThreadCtx_t *thread_ctx = (ctx->type == W_REC) ?
572 WRAPPER_THREAD_RECORD : WRAPPER_THREAD_PLAYBACK;
573 wrapper_threadWait(thread_ctx);
574 return 0;
575}
576
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800577/*return condition, locked if condition == true*/
Gong Kefdb31922022-06-17 17:11:16 +0800578static int wrapper_mutex_lock_if(DVR_WrapperMutex_t *lock, int *condition)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800579{
580 int r2;
581 do {
582 struct timespec rt2;
Gong Kefdb31922022-06-17 17:11:16 +0800583 get_timespec_timeout(10, &rt2);
584 r2 = wrapper_mutex_timedlock(lock, &rt2);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800585 } while (*condition && (r2 == ETIMEDOUT));
586
587 if (!(*condition) && (r2 == 0))
Gong Kefdb31922022-06-17 17:11:16 +0800588 wrapper_mutex_unlock(lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800589
590 return *condition;
591}
592
593static void *wrapper_task(void *arg)
594{
Wentao MA270dc0f2022-08-23 13:17:26 +0800595 DVR_WrapperThreadCtx_t *thread_ctx = (DVR_WrapperThreadCtx_t *)arg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800596 DVR_WrapperEventCtx_t *evt;
597
Wentao MA270dc0f2022-08-23 13:17:26 +0800598 pthread_mutex_lock(&thread_ctx->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800599
Wentao MA270dc0f2022-08-23 13:17:26 +0800600 while (thread_ctx->running) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800601 {
602 int ret;
hualing chene3797f02021-01-13 14:53:28 +0800603
Wentao MA270dc0f2022-08-23 13:17:26 +0800604 evt = (thread_ctx->type == W_REC)? ctx_getRecordEvent() : ctx_getPlaybackEvent();
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800605 if (!evt)
Wentao MA270dc0f2022-08-23 13:17:26 +0800606 ret = wrapper_threadWait(thread_ctx);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800607 }
608
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800609 while (evt) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800610 DVR_WrapperCtx_t *ctx = (evt->type == W_REC)?
611 ctx_getRecord(evt->sn) : ctx_getPlayback(evt->sn);
hualing chenbc0aec92021-03-18 14:52:40 +0800612 if (ctx == NULL) {
Wentao MA96f68962022-06-15 19:45:35 +0800613 DVR_WRAPPER_INFO("warp not get ctx.free event..\n");
hualing chenbc0aec92021-03-18 14:52:40 +0800614 goto processed;
615 }
Wentao MA270dc0f2022-08-23 13:17:26 +0800616 DVR_WRAPPER_INFO("start name(%s) sn(%d) running(%d) type(%d)\n", thread_ctx->name, (int)ctx->sn, thread_ctx->running, thread_ctx->type);
617 if (thread_ctx->running) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800618 /*
619 continue not break,
620 make all events consumed, or mem leak
621 */
Wentao MA270dc0f2022-08-23 13:17:26 +0800622 if (!wrapper_mutex_lock_if(&ctx->wrapper_lock, &thread_ctx->running))
Zhiqiang Hanef61c0a2020-04-13 15:49:24 +0800623 goto processed;
624
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800625 if (ctx_valid(ctx)) {
626 /*double check after lock*/
Zhiqiang Han3b9c9082021-11-10 10:41:09 +0800627 if (evt->sn == ctx->sn) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800628 pthread_mutex_unlock(&thread_ctx->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800629 process_handleEvents(evt, ctx);
Wentao MA270dc0f2022-08-23 13:17:26 +0800630 pthread_mutex_lock(&thread_ctx->lock);
Zhiqiang Han3b9c9082021-11-10 10:41:09 +0800631 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800632 }
Gong Kefdb31922022-06-17 17:11:16 +0800633 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800634 }
635
Zhiqiang Hanef61c0a2020-04-13 15:49:24 +0800636processed:
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800637 ctx_freeEvent(evt);
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800638
Wentao MA270dc0f2022-08-23 13:17:26 +0800639 evt = (thread_ctx->type == W_REC)? ctx_getRecordEvent() : ctx_getPlaybackEvent();
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800640 }
Wentao MA270dc0f2022-08-23 13:17:26 +0800641 DVR_WRAPPER_INFO("start name(%s) running(%d) type(%d) con...\n", thread_ctx->name, thread_ctx->running, thread_ctx->type);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800642 }
643
Wentao MA270dc0f2022-08-23 13:17:26 +0800644 pthread_mutex_unlock(&thread_ctx->lock);
645 DVR_WRAPPER_INFO("end name(%s) running(%d) type(%d) end...\n", thread_ctx->name, thread_ctx->running, thread_ctx->type);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800646 return NULL;
647}
648
649static inline int ctx_addRecordEvent(DVR_WrapperEventCtx_t *evt)
650{
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800651 pthread_mutex_lock(&WRAPPER_THREAD_RECORD->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800652 if (ctx_addEvent(&record_evt_list, &record_evt_list_lock, evt) == 0)
653 wrapper_threadSignalForType(evt->type);
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800654 pthread_mutex_unlock(&WRAPPER_THREAD_RECORD->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800655 return 0;
656}
657
658static inline int ctx_addPlaybackEvent(DVR_WrapperEventCtx_t *evt)
659{
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800660 pthread_mutex_lock(&WRAPPER_THREAD_PLAYBACK->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800661 if (ctx_addEvent(&playback_evt_list, &playback_evt_list_lock, evt) == 0)
662 wrapper_threadSignalForType(evt->type);
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800663 pthread_mutex_unlock(&WRAPPER_THREAD_PLAYBACK->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800664 return 0;
665}
666
667static inline void ctx_freeSegments(DVR_WrapperCtx_t *ctx)
668{
Wentao MA270dc0f2022-08-23 13:17:26 +0800669 DVR_WrapperPlaybackSegmentInfo_t *p_seg, *p_seg_tmp;
670 list_for_each_entry_safe(p_seg, p_seg_tmp, &ctx->segments, head) {
671 list_del(&p_seg->head);
672 free(p_seg);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800673 }
674}
675
Wentao MA270dc0f2022-08-23 13:17:26 +0800676static inline void _updatePlaybackSegment(DVR_WrapperPlaybackSegmentInfo_t *p_seg,
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800677 DVR_RecordSegmentInfo_t *seg_info, int update_flags, DVR_WrapperCtx_t *ctx)
678{
679 (void)ctx;
680 if ((update_flags & U_PIDS) && (update_flags & U_STAT))
Wentao MA270dc0f2022-08-23 13:17:26 +0800681 p_seg->seg_info = *seg_info;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800682 else if (update_flags & U_PIDS) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800683 p_seg->seg_info.nb_pids = seg_info->nb_pids;
684 memcpy(p_seg->seg_info.pids, seg_info->pids, sizeof(p_seg->seg_info.pids));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800685 } else if (update_flags & U_STAT) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800686 p_seg->seg_info.duration = seg_info->duration;
687 p_seg->seg_info.size = seg_info->size;
688 p_seg->seg_info.nb_packets = seg_info->nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800689 }
hualing chen03fd4942021-07-15 15:56:41 +0800690 //update current segment duration on timeshift mode
hualing chenb9b358a2021-08-17 15:06:36 +0800691 if (ctx->playback.param_open.is_timeshift
692 || ctx_isPlay_recording(ctx->playback.param_open.location))
Wentao MA270dc0f2022-08-23 13:17:26 +0800693 dvr_playback_update_duration(ctx->playback.player,p_seg->seg_info.id,p_seg->seg_info.duration);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800694 /*no changes
695 DVR_PlaybackSegmentFlag_t flags;
Wentao MA270dc0f2022-08-23 13:17:26 +0800696 p_seg->playback_info.segment_id = p_seg->seg_info.id;
697 strncpy(p_seg->playback_info.location,
698 ctx->playback.param_open.location, sizeof(p_seg->playback_info.location));
699 p_seg->playback_info.pids = ctx->playback.pids_req;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800700 flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
701 if (ctx->record.param_open.flags | DVR_RECORD_FLAG_SCRAMBLED)
702 flags |= DVR_PLAYBACK_SEGMENT_ENCRYPTED;
Wentao MA270dc0f2022-08-23 13:17:26 +0800703 p_seg->playback_info.flags = flags;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800704 */
705}
706
707static int wrapper_updatePlaybackSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info, int update_flags)
708{
Wentao MA270dc0f2022-08-23 13:17:26 +0800709 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800710
Wentao MA96f68962022-06-15 19:45:35 +0800711 DVR_WRAPPER_INFO("timeshift, update playback segments(wrapper), seg:%lld t/s/p(%ld/%zu/%u)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800712 seg_info->id, seg_info->duration, seg_info->size, seg_info->nb_packets);
713
714 if (list_empty(&ctx->segments)) {
Wentao MA96f68962022-06-15 19:45:35 +0800715 DVR_WRAPPER_INFO("timeshift, update while no segment exists, ignore\n");
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800716 return DVR_SUCCESS;
717 }
718
719 /*normally, the last segment added will be updated*/
Wentao MA270dc0f2022-08-23 13:17:26 +0800720 p_seg =
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800721 list_first_entry(&ctx->segments, DVR_WrapperPlaybackSegmentInfo_t, head);
Wentao MA270dc0f2022-08-23 13:17:26 +0800722 if (p_seg->seg_info.id == seg_info->id) {
723 _updatePlaybackSegment(p_seg, seg_info, update_flags, ctx);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800724 } else {
Wentao MA270dc0f2022-08-23 13:17:26 +0800725 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
726 if (p_seg->seg_info.id == seg_info->id) {
727 _updatePlaybackSegment(p_seg, seg_info, update_flags, ctx);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800728 break;
729 }
730 }
731 }
732
733 /*need to notify the dvr_playback*/
hualing chenb9b358a2021-08-17 15:06:36 +0800734 if ((ctx->playback.param_open.is_timeshift/*should must be timeshift*/
735 || ctx_isPlay_recording(ctx->playback.param_open.location))
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800736 && ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_END
737 && ctx->playback.seg_status.state == DVR_PLAYBACK_STATE_PAUSE) {
738 if (
739 /*there's $TIMESHIFT_DATA_DURATION_TO_RESUME more of data in the current segment playing*/
740 (ctx->playback.seg_status.segment_id == seg_info->id
741 && (seg_info->duration >= ((time_t)ctx->playback.seg_status.time_cur + TIMESHIFT_DATA_DURATION_TO_RESUME)))
742 ||
743 /*or there's a new segment and has $TIMESHIFT_DATA_DURATION_TO_RESUME of data*/
744 (ctx->playback.seg_status.segment_id != seg_info->id
745 && (seg_info->duration >= TIMESHIFT_DATA_DURATION_TO_RESUME))
746 )
747 {
748 int error;
hualing chen36e0dfd2020-05-02 16:33:06 +0800749 //clear end event
Zhiqiang Hanb723cdb2020-05-09 11:10:29 +0800750 if (ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_END)
hualing chen36e0dfd2020-05-02 16:33:06 +0800751 ctx->playback.last_event = DVR_PLAYBACK_EVENT_TRANSITION_OK;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800752
753 error = dvr_playback_resume(ctx->playback.player);
Wentao MA96f68962022-06-15 19:45:35 +0800754 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 +0800755 ctx->sn, error,
756 seg_info->id, seg_info->duration,
757 ctx->playback.seg_status.segment_id, ctx->playback.seg_status.time_cur);
758 }
759 }
760
761 return DVR_SUCCESS;
762}
763
Wentao MA270dc0f2022-08-23 13:17:26 +0800764static void _updateRecordSegment(DVR_WrapperRecordSegmentInfo_t *p_seg,
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800765 DVR_RecordSegmentInfo_t *seg_info, int update_flags, DVR_WrapperCtx_t *ctx)
766{
767 (void)ctx;
768 if ((update_flags & U_PIDS) && (update_flags & U_STAT))
Wentao MA270dc0f2022-08-23 13:17:26 +0800769 p_seg->info = *seg_info;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800770 else if (update_flags & U_PIDS) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800771 p_seg->info.nb_pids = seg_info->nb_pids;
772 memcpy(p_seg->info.pids, seg_info->pids, sizeof(p_seg->info.pids));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800773 } else if (update_flags & U_STAT) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800774 p_seg->info.duration = seg_info->duration;
775 p_seg->info.size = seg_info->size;
776 p_seg->info.nb_packets = seg_info->nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800777 }
778}
779
780static int wrapper_updateRecordSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info, int update_flags)
781{
Wentao MA270dc0f2022-08-23 13:17:26 +0800782 DVR_WrapperRecordSegmentInfo_t *p_seg = NULL;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800783
784 /*normally, the last segment added will be updated*/
hualing chen266b9502020-04-04 17:39:39 +0800785 if (!list_empty(&ctx->segments)) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800786 p_seg =
hualing chen266b9502020-04-04 17:39:39 +0800787 list_first_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
Wentao MA270dc0f2022-08-23 13:17:26 +0800788 if (p_seg->info.id == seg_info->id) {
789 _updateRecordSegment(p_seg, seg_info, update_flags, ctx);
hualing chen266b9502020-04-04 17:39:39 +0800790 } else {
Wentao MA270dc0f2022-08-23 13:17:26 +0800791 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
792 if (p_seg->info.id == seg_info->id) {
793 _updateRecordSegment(p_seg, seg_info, update_flags, ctx);
hualing chen266b9502020-04-04 17:39:39 +0800794 break;
795 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800796 }
797 }
798 }
799
800 /*timeshift, update the segment for playback*/
801 /*
802 the playback should grab the segment info other than the id,
803 and the id will be updated by each segment-add during the recording
804 */
805 /*
806 the playback paused if no data been checked from recording,
807 should resume the player later when there's more data
808 */
hualing chenb9b358a2021-08-17 15:06:36 +0800809 int sn = 0;
810 if (ctx->record.param_open.is_timeshift ||
811 (sn = ctx_isRecord_playing(ctx->record.param_open.location))) {
812 DVR_WrapperCtx_t *ctx_playback;
813 if (ctx->record.param_open.is_timeshift)
814 ctx_playback = ctx_getPlayback(sn_timeshift_playback);
815 else
816 ctx_playback = ctx_getPlayback(sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800817
818 if (ctx_playback) {
Gong Kefdb31922022-06-17 17:11:16 +0800819 wrapper_mutex_lock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800820 if (ctx_valid(ctx_playback)
hualing chenb9b358a2021-08-17 15:06:36 +0800821 && (ctx_playback->sn == sn_timeshift_playback ||
822 ctx_playback->sn == sn)) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800823 wrapper_updatePlaybackSegment(ctx_playback, seg_info, update_flags);
824 }
Gong Kefdb31922022-06-17 17:11:16 +0800825 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800826 }
827 }
828
829 return DVR_SUCCESS;
830}
831
832static int wrapper_addPlaybackSegment(DVR_WrapperCtx_t *ctx,
833 DVR_RecordSegmentInfo_t *seg_info,
834 DVR_PlaybackPids_t *p_pids,
835 DVR_PlaybackSegmentFlag_t flags)
836{
Wentao MA270dc0f2022-08-23 13:17:26 +0800837 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800838 int error;
839
840 error = 0;
Wentao MA270dc0f2022-08-23 13:17:26 +0800841 p_seg = (DVR_WrapperPlaybackSegmentInfo_t *)calloc(1, sizeof(DVR_WrapperPlaybackSegmentInfo_t));
842 if (!p_seg) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800843 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +0800844 DVR_WRAPPER_INFO("memory fail\n");
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800845 return error;
846 }
847
Wentao MA270dc0f2022-08-23 13:17:26 +0800848 /*copy the original segment info*/
849 p_seg->seg_info = *seg_info;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800850 /*generate the segment info used in playback*/
Wentao MA270dc0f2022-08-23 13:17:26 +0800851 p_seg->playback_info.segment_id = p_seg->seg_info.id;
Wentao MAe88ad702022-09-02 10:35:00 +0800852 const int len = strlen(ctx->playback.param_open.location);
853 if (len >= DVR_MAX_LOCATION_SIZE || len <= 0) {
854 DVR_WRAPPER_ERROR("Invalid playback.param_open.location length %d", len);
Wentao MA4d85ff32022-09-23 11:36:18 +0800855 free(p_seg);
Wentao MAe88ad702022-09-02 10:35:00 +0800856 return DVR_FAILURE;
857 }
858 strncpy(p_seg->playback_info.location, ctx->playback.param_open.location, len+1);
Wentao MA270dc0f2022-08-23 13:17:26 +0800859 p_seg->playback_info.pids = *p_pids;
860 p_seg->playback_info.flags = flags;
861 list_add(&p_seg->head, &ctx->segments);
862 DVR_WRAPPER_INFO("start to add segment %lld\n", p_seg->playback_info.segment_id);
863 p_seg->playback_info.duration = p_seg->seg_info.duration;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800864
Wentao MA270dc0f2022-08-23 13:17:26 +0800865 error = dvr_playback_add_segment(ctx->playback.player, &p_seg->playback_info);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800866 if (error) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800867 DVR_WRAPPER_INFO("fail to add segment %lld (%d)\n", p_seg->playback_info.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800868 } else {
Wentao MA270dc0f2022-08-23 13:17:26 +0800869 ctx->playback.status.info_full.time += p_seg->seg_info.duration;
870 ctx->playback.status.info_full.size += p_seg->seg_info.size;
871 ctx->playback.status.info_full.pkts += p_seg->seg_info.nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800872 }
873
874 return error;
875}
876
877static int wrapper_addRecordSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info)
878{
Wentao MA270dc0f2022-08-23 13:17:26 +0800879 DVR_WrapperRecordSegmentInfo_t *p_seg;
Wentao MA16f870e2022-09-09 11:00:22 +0800880 int error = DVR_SUCCESS;
hualing chenab0d1262021-09-26 15:22:50 +0800881 int sn = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800882
Wentao MA270dc0f2022-08-23 13:17:26 +0800883 p_seg = (DVR_WrapperRecordSegmentInfo_t *)calloc(1, sizeof(DVR_WrapperRecordSegmentInfo_t));
884 if (!p_seg) {
Wentao MA16f870e2022-09-09 11:00:22 +0800885 DVR_WRAPPER_ERROR("memory allocation failed");
886 return DVR_FAILURE;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800887 }
Wentao MA270dc0f2022-08-23 13:17:26 +0800888 p_seg->info = *seg_info;
889 list_add(&p_seg->head, &ctx->segments);
hualing chenab0d1262021-09-26 15:22:50 +0800890
hualing chenb9b358a2021-08-17 15:06:36 +0800891 if (ctx->record.param_open.is_timeshift ||
892 (sn = ctx_isRecord_playing(ctx->record.param_open.location))) {
893
894 DVR_WrapperCtx_t *ctx_playback;
895 if (ctx->record.param_open.is_timeshift)
896 ctx_playback = ctx_getPlayback(sn_timeshift_playback);
897 else
898 ctx_playback = ctx_getPlayback(sn);
899
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800900 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: playback(sn:%ld) add seg\n", ctx->sn, sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800901
902 if (ctx_playback) {
Gong Kefdb31922022-06-17 17:11:16 +0800903 wrapper_mutex_lock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800904 if (ctx_valid(ctx_playback)) {
905 DVR_PlaybackSegmentFlag_t flags;
906
907 /*only if playback has started, the previous segments have been loaded*/
908 if (!list_empty(&ctx_playback->segments)) {
909 flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
Gong Ke2a0ebbe2021-05-25 15:22:50 +0800910 if (ctx->record.param_open.flags & DVR_RECORD_FLAG_SCRAMBLED)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800911 flags |= DVR_PLAYBACK_SEGMENT_ENCRYPTED;
wentao.maa210e5e2022-10-12 16:10:03 +0800912 error = wrapper_addPlaybackSegment(ctx_playback, seg_info, &ctx_playback->playback.pids_req, flags);
913 if (error == DVR_FAILURE) {
914 DVR_WRAPPER_WARN("adding playback segment fails");
915 }
hualing chen451c8f72022-03-09 13:05:52 +0800916 } else {
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800917 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: playback(sn:%ld) list empty\n", ctx->sn, sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800918 }
hualing chenb9b358a2021-08-17 15:06:36 +0800919 } else {
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800920 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: playback(sn:%ld) not valid\n", ctx->sn, sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800921 }
Gong Kefdb31922022-06-17 17:11:16 +0800922 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800923 }
hualing chen451c8f72022-03-09 13:05:52 +0800924 else
925 {
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800926 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: playback(sn:%ld) not valid 2\n", ctx->sn, sn);
927 }
928
929 /*if it is not a timeshift recording, but a playing recording,
930 do not forget to obey the recording rule: link the segment!*/
931 if (!ctx->record.param_open.is_timeshift) {
932 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: update link\n", ctx->sn);
933 dvr_segment_link_op(ctx->record.param_open.location, 1, &seg_info->id, SEGMENT_OP_ADD);
hualing chen451c8f72022-03-09 13:05:52 +0800934 }
Zhiqiang Hane0a1c382021-06-08 11:28:05 +0800935 } else {
Zhiqiang Hanfd72b592022-07-04 18:36:52 +0800936 DVR_WRAPPER_INFO("rec(sn:%ld) add_seg: update link\n", ctx->sn);
Wentao MAe8ba5172022-08-09 11:18:17 +0800937 dvr_segment_link_op(ctx->record.param_open.location, 1, &seg_info->id, SEGMENT_OP_ADD);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800938 }
939
940 return error;
941}
942
943static int wrapper_removePlaybackSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info)
944{
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800945 int error = -1;
Wentao MA270dc0f2022-08-23 13:17:26 +0800946 DVR_WrapperPlaybackSegmentInfo_t *p_seg = NULL, *p_seg_tmp;
hualing chenb9a1a2c2021-12-31 11:27:59 +0800947 uint32_t off_set = 0;
Wentao MA96f68962022-06-15 19:45:35 +0800948 DVR_WRAPPER_INFO("timeshift, remove playback(sn:%ld) segment(%lld) ...\n", ctx->sn, seg_info->id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800949
Wentao MA270dc0f2022-08-23 13:17:26 +0800950 list_for_each_entry_safe_reverse(p_seg, p_seg_tmp, &ctx->segments, head) {
951 if (p_seg->seg_info.id == seg_info->id) {
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800952
953 if (ctx->current_segment_id == seg_info->id) {
954 DVR_WrapperPlaybackSegmentInfo_t *next_seg;
955
956 /*drive the player out of this will-be-deleted segment*/
Wentao MA270dc0f2022-08-23 13:17:26 +0800957 next_seg = list_prev_entry(p_seg, head);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800958
959 if (ctx->playback.speed != 100.0f) {
960 error = dvr_playback_resume(ctx->playback.player);
Wentao MA96f68962022-06-15 19:45:35 +0800961 DVR_WRAPPER_INFO("timeshift, playback(sn:%ld), resume for new start (%d)\n", ctx->sn, error);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800962 }
hualing chenb9a1a2c2021-12-31 11:27:59 +0800963 if (ctx->playback.param_open.vendor == DVR_PLAYBACK_VENDOR_AMAZON)
964 off_set = 10 * 1000;
965 error = dvr_playback_seek(ctx->playback.player, next_seg->seg_info.id, off_set);
Wentao MA96f68962022-06-15 19:45:35 +0800966 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 +0800967
968 if (ctx->playback.speed == 0.0f) {
969 error = dvr_playback_pause(ctx->playback.player, DVR_FALSE);
Wentao MA96f68962022-06-15 19:45:35 +0800970 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 +0800971 } else if (ctx->playback.speed != 100.0f) {
972 DVR_PlaybackSpeed_t dvr_speed = {
973 .speed = { ctx->playback.speed },
974 .mode = ( ctx->playback.speed > 0) ? DVR_PLAYBACK_FAST_FORWARD : DVR_PLAYBACK_FAST_BACKWARD
975 };
976 error = dvr_playback_set_speed(ctx->playback.player, dvr_speed);
Wentao MA96f68962022-06-15 19:45:35 +0800977 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 +0800978 }
979 }
980
981 error = dvr_playback_remove_segment(ctx->playback.player, seg_info->id);
982 if (error) {
Wentao MA270dc0f2022-08-23 13:17:26 +0800983 /*remove playback segment fail*/
Wentao MA96f68962022-06-15 19:45:35 +0800984 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 +0800985 }
986
Wentao MA270dc0f2022-08-23 13:17:26 +0800987 list_del(&p_seg->head);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800988
989 /*record the obsolete*/
Wentao MA270dc0f2022-08-23 13:17:26 +0800990 ctx->playback.obsolete.time += p_seg->seg_info.duration;
991 ctx->playback.obsolete.size += p_seg->seg_info.size;
992 ctx->playback.obsolete.pkts += p_seg->seg_info.nb_packets;
Wentao MA96f68962022-06-15 19:45:35 +0800993 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 +0800994 dvr_playback_set_obsolete(ctx->playback.player, ctx->playback.obsolete.time);
Wentao MA270dc0f2022-08-23 13:17:26 +0800995 free(p_seg);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800996 break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800997 }
998 }
999
Wentao MA96f68962022-06-15 19:45:35 +08001000 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 +08001001
1002 return error;
1003}
1004
1005static int wrapper_removeRecordSegment(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordSegmentInfo_t *seg_info)
1006{
1007 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08001008 DVR_WrapperRecordSegmentInfo_t *p_seg, *p_seg_tmp;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001009
Wentao MAf4072032022-06-30 13:50:45 +08001010 DVR_WRAPPER_INFO("calling %s on record(sn:%ld) segment(%lld) ...",
1011 __func__, ctx->sn, seg_info->info.id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001012
1013 /*if timeshifting, notify the playback first, then deal with record*/
1014 if (ctx->record.param_open.is_timeshift) {
1015 DVR_WrapperCtx_t *ctx_playback = ctx_getPlayback(sn_timeshift_playback);
1016
1017 if (ctx_playback) {
Gong Kefdb31922022-06-17 17:11:16 +08001018 wrapper_mutex_lock(&ctx_playback->wrapper_lock);
hualing chen56c0a162022-01-27 17:01:50 +08001019 if (ctx_playback->current_segment_id == seg_info->info.id && ctx_playback->playback.speed == 100.0f) {
1020 ctx_playback->playback.tf_full = DVR_TRUE;
Wentao MAf4072032022-06-30 13:50:45 +08001021 DVR_WRAPPER_INFO("%s, cannot remove record(sn:%ld) segment(%lld) for it is being"
1022 " played on segment(%lld) at speed %f.", __func__, ctx->sn, seg_info->info.id,
1023 ctx_playback->current_segment_id, ctx_playback->playback.speed);
Gong Kefdb31922022-06-17 17:11:16 +08001024 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
hualing chen56c0a162022-01-27 17:01:50 +08001025 return DVR_SUCCESS;
1026 } else {
Wentao MAf4072032022-06-30 13:50:45 +08001027 DVR_WRAPPER_INFO("%s, removing record(sn:%ld) segment(%lld) which is being played "
1028 "on segment (%lld) at speed (%f).", __func__, ctx->sn, seg_info->info.id,
1029 ctx_playback->current_segment_id,ctx_playback->playback.speed);
hualing chen56c0a162022-01-27 17:01:50 +08001030 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001031 if (ctx_valid(ctx_playback)
1032 && ctx_playback->sn == sn_timeshift_playback
1033 && !list_empty(&ctx_playback->segments)) {
1034 error = wrapper_removePlaybackSegment(ctx_playback, &seg_info->info);
Wentao MA07d3d742022-09-06 09:58:05 +08001035 if (error != DVR_SUCCESS) {
1036 DVR_WRAPPER_ERROR("wrapper_removePlaybackSegment failed with return value %d",error);
1037 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001038 }
hualing chen56c0a162022-01-27 17:01:50 +08001039 ctx_playback->playback.tf_full = DVR_FALSE;
Gong Kefdb31922022-06-17 17:11:16 +08001040 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001041 }
1042 }
1043
Zhiqiang Hanbc3019b2022-03-21 11:31:21 +08001044 uint64_t id = seg_info->info.id;
1045
Wentao MA270dc0f2022-08-23 13:17:26 +08001046 list_for_each_entry_safe_reverse(p_seg, p_seg_tmp, &ctx->segments, head) {
1047 if (p_seg->info.id == id) {
1048 list_del(&p_seg->head);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001049
1050 /*record the obsolete*/
Wentao MA270dc0f2022-08-23 13:17:26 +08001051 ctx->record.obsolete.time += p_seg->info.duration;
1052 ctx->record.obsolete.size += p_seg->info.size;
1053 ctx->record.obsolete.pkts += p_seg->info.nb_packets;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001054
Wentao MA270dc0f2022-08-23 13:17:26 +08001055 free(p_seg);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001056 break;
1057 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001058 }
1059
Zhiqiang Hanbc3019b2022-03-21 11:31:21 +08001060 error = dvr_segment_delete(ctx->record.param_open.location, id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001061
Wentao MAf4072032022-06-30 13:50:45 +08001062 DVR_WRAPPER_INFO("%s, removed record(sn:%ld) segment(%lld), ret=(%d)\n",
1063 __func__, ctx->sn, id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001064
1065 return error;
1066}
1067
1068int dvr_wrapper_open_record (DVR_WrapperRecord_t *rec, DVR_WrapperRecordOpenParams_t *params)
1069{
1070 int error;
1071 DVR_WrapperCtx_t *ctx;
1072 DVR_RecordOpenParams_t open_param;
1073
1074 DVR_RETURN_IF_FALSE(rec);
1075 DVR_RETURN_IF_FALSE(params);
1076
1077 /*get a free ctx*/
1078 ctx = ctx_getRecord(0);
1079 DVR_RETURN_IF_FALSE(ctx);
1080
Gong Kefdb31922022-06-17 17:11:16 +08001081 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001082
Wentao MA9a164002022-08-29 11:20:24 +08001083 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 +08001084 params->dmx_dev_id, params->is_timeshift, params->max_time, params->max_size, params->segment_size);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001085
1086 ctx_reset(ctx);
1087
1088 ctx->record.param_open = *params;
1089 ctx->record.event_fn = params->event_fn;
1090 ctx->record.event_userdata = params->event_userdata;
1091 ctx->record.next_segment_id = 0;
1092 ctx->current_segment_id = 0;
1093 INIT_LIST_HEAD(&ctx->segments);
1094 ctx->sn = get_sn();
1095
1096 wrapper_requestThreadFor(ctx);
1097
hualing chen266b9502020-04-04 17:39:39 +08001098 memset(&open_param, 0, sizeof(DVR_RecordOpenParams_t));
Yahui Hance15e9c2020-12-08 18:08:32 +08001099 open_param.fend_dev_id = params->fend_dev_id;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001100 open_param.dmx_dev_id = params->dmx_dev_id;
1101 open_param.data_from_memory = 0;
1102 open_param.flags = params->flags;
Yahui Han15a00f12021-11-15 19:44:39 +08001103 if (params->flush_size) {
1104 open_param.notification_size = params->flush_size;
1105 } else {
1106 open_param.notification_size = 64*1024;
1107 }
hualing chen002e5b92022-02-23 17:51:21 +08001108 open_param.notification_time = 400;//ms
Zhiqiang Han31505452020-05-06 15:08:10 +08001109 open_param.flush_size = params->flush_size;
hualing chen03fd4942021-07-15 15:56:41 +08001110 open_param.ringbuf_size = params->ringbuf_size;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001111 open_param.event_fn = wrapper_record_event_handler;
1112 open_param.event_userdata = (void*)ctx->sn;
Yahui Han1fbf3292021-11-08 18:17:19 +08001113 if (params->keylen) {
1114 open_param.clearkey = params->clearkey;
1115 open_param.cleariv = params->cleariv;
1116 open_param.keylen = params->keylen;
1117 }
wentao.ma35a69d42022-03-10 18:08:40 +08001118 open_param.force_sysclock = params->force_sysclock;
Wentao MAeeffdb02022-06-27 16:34:35 +08001119 open_param.guarded_segment_size = params->segment_size/2*3;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001120
1121 error = dvr_record_open(&ctx->record.recorder, &open_param);
1122 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001123 DVR_WRAPPER_INFO("record(dmx:%d) open fail(error:%d).\n", params->dmx_dev_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001124 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001125 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001126 wrapper_releaseThreadForType(ctx->type);
1127 return DVR_FAILURE;
1128 }
1129 if (params->is_timeshift)
1130 sn_timeshift_record = ctx->sn;
1131
Wentao MA96f68962022-06-15 19:45:35 +08001132 DVR_WRAPPER_INFO("record(dmx:%d) openned ok(sn:%ld).\n", params->dmx_dev_id, ctx->sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001133
Yahui Han1fbf3292021-11-08 18:17:19 +08001134 if (params->crypto_fn) {
1135 error = dvr_record_set_encrypt_callback(ctx->record.recorder, params->crypto_fn, params->crypto_data);
1136 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001137 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 +08001138 }
hualing chen266b9502020-04-04 17:39:39 +08001139 }
1140
Gong Kefdb31922022-06-17 17:11:16 +08001141 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001142
1143 *rec = (DVR_WrapperRecord_t)ctx->sn;
1144 return DVR_SUCCESS;
1145}
1146
1147int dvr_wrapper_close_record (DVR_WrapperRecord_t rec)
1148{
1149 DVR_WrapperCtx_t *ctx;
1150 DVR_RecordSegmentInfo_t seg_info;
1151 int error;
1152
1153 DVR_RETURN_IF_FALSE(rec);
1154
1155 ctx = ctx_getRecord((unsigned long)rec);
1156 DVR_RETURN_IF_FALSE(ctx);
1157
Gong Kefdb31922022-06-17 17:11:16 +08001158 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001159 DVR_WRAPPER_INFO("close record(sn:%ld)\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001160 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001161
1162 memset(&seg_info, 0, sizeof(seg_info));
wentao.maa210e5e2022-10-12 16:10:03 +08001163 dvr_record_stop_segment(ctx->record.recorder, &seg_info);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001164
1165 error = dvr_record_close(ctx->record.recorder);
1166
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001167 if (ctx->record.param_open.is_timeshift)
1168 sn_timeshift_record = 0;
1169
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001170 ctx_freeSegments(ctx);
1171
Wentao MA96f68962022-06-15 19:45:35 +08001172 DVR_WRAPPER_INFO("record(sn:%ld) closed = (%d).\n", ctx->sn, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001173 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001174 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001175
1176 wrapper_releaseThreadForType(ctx->type);
1177
1178 return error;
1179}
1180
1181int dvr_wrapper_start_record (DVR_WrapperRecord_t rec, DVR_WrapperRecordStartParams_t *params)
1182{
1183 DVR_WrapperCtx_t *ctx;
1184 DVR_RecordStartParams_t *start_param;
1185 int i;
1186 int error;
1187
1188 DVR_RETURN_IF_FALSE(rec);
1189 DVR_RETURN_IF_FALSE(params);
1190
1191 ctx = ctx_getRecord((unsigned long)rec);
1192 DVR_RETURN_IF_FALSE(ctx);
1193
Gong Kefdb31922022-06-17 17:11:16 +08001194 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001195 DVR_WRAPPER_INFO("start record(sn:%ld, location:%s) save(%d)...\n", ctx->sn, ctx->record.param_open.location, params->save_rec_file);
Gong Kefdb31922022-06-17 17:11:16 +08001196 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001197
1198 start_param = &ctx->record.param_start;
1199 memset(start_param, 0, sizeof(*start_param));
Wentao MAe88ad702022-09-02 10:35:00 +08001200 const int len = strlen(ctx->record.param_open.location);
1201 if (len >= DVR_MAX_LOCATION_SIZE || len <= 0) {
1202 DVR_WRAPPER_ERROR("Invalid record.param_open.location length %d",len);
1203 pthread_mutex_unlock(&ctx->wrapper_lock);
1204 return DVR_FAILURE;
1205 }
1206 strncpy(start_param->location, ctx->record.param_open.location, len+1);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001207 start_param->segment.segment_id = ctx->record.next_segment_id++;
1208 start_param->segment.nb_pids = params->pids_info.nb_pids;
1209 for (i = 0; i < params->pids_info.nb_pids; i++) {
1210 start_param->segment.pids[i] = params->pids_info.pids[i];
1211 start_param->segment.pid_action[i] = DVR_RECORD_PID_CREATE;
1212 }
hualing chena5f03222021-12-02 11:22:35 +08001213 if (params->save_rec_file == 0)//default is not save
1214 dvr_segment_del_by_location(start_param->location);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001215 {
1216 /*sync to update for further use*/
1217 DVR_RecordStartParams_t *update_param;
1218 update_param = &ctx->record.param_update;
1219 memcpy(update_param, start_param, sizeof(*update_param));
1220 for (i = 0; i < update_param->segment.nb_pids; i++)
1221 update_param->segment.pid_action[i] = DVR_RECORD_PID_KEEP;
1222 }
1223
1224 error = dvr_record_start_segment(ctx->record.recorder, start_param);
1225 {
1226 DVR_RecordSegmentInfo_t new_seg_info =
1227 { .id = start_param->segment.segment_id, };
1228 wrapper_addRecordSegment(ctx, &new_seg_info);
1229 }
1230
Wentao MA96f68962022-06-15 19:45:35 +08001231 DVR_WRAPPER_INFO("record(sn:%ld) started = (%d)\n", ctx->sn, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001232
Gong Kefdb31922022-06-17 17:11:16 +08001233 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001234
1235 return error;
1236}
1237
1238int dvr_wrapper_stop_record (DVR_WrapperRecord_t rec)
1239{
1240 DVR_WrapperCtx_t *ctx;
1241 DVR_RecordSegmentInfo_t seg_info;
1242 int error;
1243
1244 DVR_RETURN_IF_FALSE(rec);
1245
1246 ctx = ctx_getRecord((unsigned long)rec);
1247 DVR_RETURN_IF_FALSE(ctx);
1248
Gong Kefdb31922022-06-17 17:11:16 +08001249 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001250 DVR_WRAPPER_INFO("stop record(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001251 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001252
1253 memset(&seg_info, 0, sizeof(seg_info));
1254 error = dvr_record_stop_segment(ctx->record.recorder, &seg_info);
1255 wrapper_updateRecordSegment(ctx, &seg_info, U_ALL);
1256
Wentao MA96f68962022-06-15 19:45:35 +08001257 DVR_WRAPPER_INFO("record(sn:%ld) stopped = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001258 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001259
1260 return error;
1261}
1262
hualing chen03fd4942021-07-15 15:56:41 +08001263int dvr_wrapper_pause_record (DVR_WrapperRecord_t rec)
1264{
1265 DVR_WrapperCtx_t *ctx;
1266 int error;
1267
1268 DVR_RETURN_IF_FALSE(rec);
1269
1270 ctx = ctx_getRecord((unsigned long)rec);
1271 DVR_RETURN_IF_FALSE(ctx);
1272
Gong Kefdb31922022-06-17 17:11:16 +08001273 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001274 DVR_WRAPPER_INFO("pause record(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001275 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001276
1277 error = dvr_record_pause(ctx->record.recorder);
1278
Wentao MA96f68962022-06-15 19:45:35 +08001279 DVR_WRAPPER_INFO("record(sn:%ld) pauseed = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001280 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001281
1282 return error;
1283}
1284
1285int dvr_wrapper_resume_record (DVR_WrapperRecord_t rec)
1286{
1287 DVR_WrapperCtx_t *ctx;
1288 int error;
1289
1290 DVR_RETURN_IF_FALSE(rec);
1291
1292 ctx = ctx_getRecord((unsigned long)rec);
1293 DVR_RETURN_IF_FALSE(ctx);
1294
Gong Kefdb31922022-06-17 17:11:16 +08001295 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001296 DVR_WRAPPER_INFO("resume record(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001297 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001298
1299 error = dvr_record_resume(ctx->record.recorder);
1300
Wentao MA96f68962022-06-15 19:45:35 +08001301 DVR_WRAPPER_INFO("record(sn:%ld) resumed = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001302 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001303
1304 return error;
1305}
1306
Wentao MAcdea4762022-04-26 13:28:56 +08001307/* Return true if arr1 contains all elements in arr2 */
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001308static DVR_Bool_t pids_test_include(
1309 DVR_StreamPid_t* arr1, DVR_RecordPidAction_t *act1, int size1,
1310 DVR_StreamPid_t* arr2, DVR_RecordPidAction_t *act2, int size2)
wentao.maa69578c2022-04-07 09:27:39 +08001311{
Wentao MAcdea4762022-04-26 13:28:56 +08001312 DVR_Bool_t ret = DVR_TRUE;
1313 for (int i=0;i<size2;i++)
1314 { // iterate all elements in arr2 to check if they exist in arr1
1315 DVR_Bool_t found=DVR_FALSE;
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001316
1317 if (act2[i] == DVR_RECORD_PID_CLOSE)
1318 continue;
1319
Wentao MAcdea4762022-04-26 13:28:56 +08001320 for (int j=0;j<size1;j++)
wentao.maa69578c2022-04-07 09:27:39 +08001321 {
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001322 if (act1[j] != DVR_RECORD_PID_CLOSE
1323 && arr2[i].pid == arr1[j].pid)
wentao.maa69578c2022-04-07 09:27:39 +08001324 {
1325 found=DVR_TRUE;
1326 break;
1327 }
1328 }
1329 if (found == DVR_FALSE)
1330 {
Wentao MAcdea4762022-04-26 13:28:56 +08001331 ret=DVR_FALSE;
wentao.maa69578c2022-04-07 09:27:39 +08001332 break;
1333 }
1334 }
Wentao MAcdea4762022-04-26 13:28:56 +08001335 return ret;
1336}
1337
1338static DVR_Bool_t pids_equal(const DVR_RecordSegmentStartParams_t* p1,
1339 const DVR_WrapperUpdatePidsParams_t* p2)
1340{
1341 int i=0;
1342 char buf[128]={0};
1343 int cnt=0;
1344 int chars=0;
1345
1346 DVR_RETURN_IF_FALSE(p1 != NULL && p2 != NULL);
1347 DVR_RETURN_IF_FALSE(p1->nb_pids>0 && p2->nb_pids>0);
1348
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001349 DVR_Bool_t cond1 = pids_test_include(p1->pids,p1->pid_action,p1->nb_pids,
1350 p2->pids,p2->pid_action,p2->nb_pids);
1351 DVR_Bool_t cond2 = pids_test_include(p2->pids,p2->pid_action,p2->nb_pids,
1352 p1->pids,p1->pid_action,p1->nb_pids);
Wentao MAcdea4762022-04-26 13:28:56 +08001353 DVR_Bool_t is_equal = (cond1 && cond2);
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001354 int removed;
Wentao MAcdea4762022-04-26 13:28:56 +08001355
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001356 removed = 0;
Wentao MAcdea4762022-04-26 13:28:56 +08001357 for (i=0;i<p1->nb_pids;i++)
1358 {
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001359 if (p1->pid_action[i] == DVR_RECORD_PID_CLOSE) {
1360 removed++;
1361 continue;
1362 }
Wentao MAcdea4762022-04-26 13:28:56 +08001363 chars = snprintf(buf+cnt,sizeof(buf)-cnt,"0x%hx,",p1->pids[i].pid);
1364 if (chars<0)
1365 {
1366 break;
1367 }
1368 cnt += chars;
1369 }
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001370 DVR_INFO("%s nb_pids1:%d, pids1: %s",__func__,p1->nb_pids-removed,buf);
Wentao MAcdea4762022-04-26 13:28:56 +08001371 memset(buf,0,sizeof(buf));
1372
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001373 removed = 0;
Wentao MAcdea4762022-04-26 13:28:56 +08001374 for (i=0,cnt=0;i<p2->nb_pids;i++)
1375 {
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001376 if (p2->pid_action[i] == DVR_RECORD_PID_CLOSE) {
1377 removed++;
1378 continue;
1379 }
Wentao MAcdea4762022-04-26 13:28:56 +08001380 chars = snprintf(buf+cnt,sizeof(buf)-cnt,"0x%hx,",p2->pids[i].pid);
1381 if (chars<0)
1382 {
1383 break;
1384 }
1385 cnt += chars;
1386 }
Zhiqiang Han42d91aa2022-08-10 16:38:12 +08001387 DVR_INFO("%s nb_pids2:%d, pids2: %s",__func__,p2->nb_pids-removed,buf);
Wentao MA96f68962022-06-15 19:45:35 +08001388 DVR_INFO("%s is_equal:%d",__func__,is_equal);
wentao.maa69578c2022-04-07 09:27:39 +08001389 return is_equal;
1390}
1391
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001392int dvr_wrapper_update_record_pids (DVR_WrapperRecord_t rec, DVR_WrapperUpdatePidsParams_t *params)
1393{
1394 DVR_WrapperCtx_t *ctx;
1395 DVR_RecordStartParams_t *start_param;
wentao.maa69578c2022-04-07 09:27:39 +08001396 DVR_RecordSegmentInfo_t seg_info;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001397 int i;
1398 int error;
1399
1400 DVR_RETURN_IF_FALSE(rec);
1401 DVR_RETURN_IF_FALSE(params);
1402
1403 ctx = ctx_getRecord((unsigned long)rec);
1404 DVR_RETURN_IF_FALSE(ctx);
1405
Gong Kefdb31922022-06-17 17:11:16 +08001406 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001407 DVR_WRAPPER_INFO("update record(sn:%ld)\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001408 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001409
1410 start_param = &ctx->record.param_update;
wentao.maa69578c2022-04-07 09:27:39 +08001411 if (pids_equal(&(start_param->segment),params))
1412 {
Gong Kefdb31922022-06-17 17:11:16 +08001413 wrapper_mutex_unlock(&ctx->wrapper_lock);
wentao.maa69578c2022-04-07 09:27:39 +08001414 return DVR_TRUE;
1415 }
1416
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001417 memset(start_param, 0, sizeof(*start_param));
Wentao MAe88ad702022-09-02 10:35:00 +08001418 const int len = strlen(ctx->record.param_open.location);
1419 if (len >= DVR_MAX_LOCATION_SIZE || len <= 0) {
1420 DVR_WRAPPER_ERROR("Invalid record.param_open.location length %d",len);
1421 pthread_mutex_unlock(&ctx->wrapper_lock);
1422 return DVR_FAILURE;
1423 }
1424 strncpy(start_param->location, ctx->record.param_open.location, len+1);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001425 start_param->segment.segment_id = ctx->record.next_segment_id++;
1426 start_param->segment.nb_pids = params->nb_pids;
1427 for (i = 0; i < params->nb_pids; i++) {
1428 start_param->segment.pids[i] = params->pids[i];
1429 start_param->segment.pid_action[i] = params->pid_action[i];
1430 }
1431 error = dvr_record_next_segment(ctx->record.recorder, start_param, &seg_info);
1432 {
1433 DVR_RecordSegmentInfo_t new_seg_info =
1434 { .id = start_param->segment.segment_id, };
1435 wrapper_updateRecordSegment(ctx, &seg_info, U_PIDS);
1436 wrapper_addRecordSegment(ctx, &new_seg_info);
1437 }
1438
Wentao MA96f68962022-06-15 19:45:35 +08001439 DVR_WRAPPER_INFO("record(sn:%ld) updated = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001440 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001441
1442 return error;
1443}
1444
1445int dvr_wrapper_get_record_status(DVR_WrapperRecord_t rec, DVR_WrapperRecordStatus_t *status)
1446{
1447 DVR_WrapperCtx_t *ctx;
1448 DVR_WrapperRecordStatus_t s;
1449 int error;
1450
1451 DVR_RETURN_IF_FALSE(rec);
1452 DVR_RETURN_IF_FALSE(status);
1453
1454 ctx = ctx_getRecord((unsigned long)rec);
1455 DVR_RETURN_IF_FALSE(ctx);
1456
Gong Kefdb31922022-06-17 17:11:16 +08001457 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001458
Wentao MA96f68962022-06-15 19:45:35 +08001459 DVR_WRAPPER_INFO("get record(sn:%ld) status ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001460 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001461
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001462 error = process_generateRecordStatus(ctx, &s);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001463
Wentao MA96f68962022-06-15 19:45:35 +08001464 DVR_WRAPPER_INFO("record(sn:%ld) state/time/size/pkts(%d/%ld/%lld/%u) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001465 ctx->sn,
1466 s.state,
1467 s.info.time,
1468 s.info.size,
1469 s.info.pkts,
1470 error);
1471
1472 *status = s;
1473
Gong Kefdb31922022-06-17 17:11:16 +08001474 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001475
1476 return error;
1477}
1478
hualing chen4fe3bee2020-10-23 13:58:52 +08001479int dvr_wrapper_record_is_secure_mode(DVR_WrapperRecord_t rec)
1480{
1481 DVR_WrapperCtx_t *ctx;
1482 int error;
1483
1484 DVR_RETURN_IF_FALSE(rec);
1485
1486 ctx = ctx_getRecord((unsigned long)rec);
1487 DVR_RETURN_IF_FALSE(ctx);
1488
Gong Kefdb31922022-06-17 17:11:16 +08001489 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen4fe3bee2020-10-23 13:58:52 +08001490 error = dvr_record_is_secure_mode(ctx->record.recorder);
Gong Kefdb31922022-06-17 17:11:16 +08001491 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen4fe3bee2020-10-23 13:58:52 +08001492 return error;
1493}
1494
hualing chen266b9502020-04-04 17:39:39 +08001495int dvr_wrapper_set_record_secure_buffer (DVR_WrapperRecord_t rec, uint8_t *p_secure_buf, uint32_t len)
1496{
1497 DVR_WrapperCtx_t *ctx;
1498 int error;
1499
1500 DVR_RETURN_IF_FALSE(rec);
1501 DVR_RETURN_IF_FALSE(p_secure_buf);
1502
1503 ctx = ctx_getRecord((unsigned long)rec);
1504 DVR_RETURN_IF_FALSE(ctx);
1505
Gong Kefdb31922022-06-17 17:11:16 +08001506 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001507 error = dvr_record_set_secure_buffer(ctx->record.recorder, p_secure_buf, len);
Gong Kefdb31922022-06-17 17:11:16 +08001508 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001509 return error;
1510}
1511
1512int dvr_wrapper_set_record_decrypt_callback (DVR_WrapperRecord_t rec, DVR_CryptoFunction_t func, void *userdata)
1513{
1514 DVR_WrapperCtx_t *ctx;
1515 int error;
1516
1517 DVR_RETURN_IF_FALSE(rec);
1518 DVR_RETURN_IF_FALSE(func);
1519
1520 ctx = ctx_getRecord((unsigned long)rec);
1521 DVR_RETURN_IF_FALSE(ctx);
1522
Gong Kefdb31922022-06-17 17:11:16 +08001523 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001524 error = dvr_record_set_encrypt_callback(ctx->record.recorder, func, userdata);
Gong Kefdb31922022-06-17 17:11:16 +08001525 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001526 return error;
1527}
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001528
1529
1530int dvr_wrapper_open_playback (DVR_WrapperPlayback_t *playback, DVR_WrapperPlaybackOpenParams_t *params)
1531{
1532 DVR_WrapperCtx_t *ctx;
1533 DVR_PlaybackOpenParams_t open_param;
1534 int error;
1535
1536 DVR_RETURN_IF_FALSE(playback);
1537 DVR_RETURN_IF_FALSE(params);
1538 DVR_RETURN_IF_FALSE(params->playback_handle);
1539
1540 /*get a free ctx*/
1541 ctx = ctx_getPlayback(0);
1542 DVR_RETURN_IF_FALSE(ctx);
1543
Gong Kefdb31922022-06-17 17:11:16 +08001544 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001545
Wentao MA96f68962022-06-15 19:45:35 +08001546 DVR_WRAPPER_INFO("open playback(dmx:%d) ..vendor[%d]params->block_size[%d].\n", params->dmx_dev_id, params->vendor, params->block_size);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001547
1548 ctx_reset(ctx);
1549
1550 ctx->playback.param_open = *params;
1551 ctx->playback.event_fn = params->event_fn;
1552 ctx->playback.event_userdata = params->event_userdata;
1553 ctx->current_segment_id = 0;
1554 INIT_LIST_HEAD(&ctx->segments);
1555 ctx->sn = get_sn();
1556
1557 wrapper_requestThreadFor(ctx);
1558
hualing chen266b9502020-04-04 17:39:39 +08001559 memset(&open_param, 0, sizeof(DVR_PlaybackOpenParams_t));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001560 open_param.dmx_dev_id = params->dmx_dev_id;
1561 open_param.block_size = params->block_size;
1562 open_param.is_timeshift = params->is_timeshift;
1563 //open_param.notification_size = 10*1024; //not supported
1564 open_param.event_fn = wrapper_playback_event_handler;
1565 open_param.event_userdata = (void*)ctx->sn;
1566 /*open_param.has_pids = 0;*/
hualing chene3797f02021-01-13 14:53:28 +08001567 open_param.is_notify_time = params->is_notify_time;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001568 open_param.player_handle = (am_tsplayer_handle)params->playback_handle;
hualing chen90b3ae62021-03-30 10:49:28 +08001569 open_param.vendor = params->vendor;
1570
Yahui Han1fbf3292021-11-08 18:17:19 +08001571 if (params->keylen) {
1572 open_param.clearkey = params->clearkey;
1573 open_param.cleariv = params->cleariv;
1574 open_param.keylen = params->keylen;
1575 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001576
1577 error = dvr_playback_open(&ctx->playback.player, &open_param);
1578 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001579 DVR_WRAPPER_INFO("playback(dmx:%d) openned fail(error:%d).\n", params->dmx_dev_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001580 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001581 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001582 wrapper_releaseThreadForType(ctx->type);
1583 return DVR_FAILURE;
1584 }
1585 if (params->is_timeshift)
1586 sn_timeshift_playback = ctx->sn;
1587
Wentao MA270dc0f2022-08-23 13:17:26 +08001588 DVR_WRAPPER_INFO("playback(dmx:%d) openned ok(sn:%ld).\n", params->dmx_dev_id, ctx->sn);
hualing chen266b9502020-04-04 17:39:39 +08001589 error = dvr_playback_set_decrypt_callback(ctx->playback.player, params->crypto_fn, params->crypto_data);
1590 if (error) {
Wentao MA270dc0f2022-08-23 13:17:26 +08001591 DVR_WRAPPER_INFO("playback set decrypt callback fail(error:%d).\n", error);
hualing chen266b9502020-04-04 17:39:39 +08001592 }
Gong Kefdb31922022-06-17 17:11:16 +08001593 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001594
1595 *playback = (DVR_WrapperPlayback_t)ctx->sn;
1596 return DVR_SUCCESS;
1597}
1598
1599int dvr_wrapper_close_playback (DVR_WrapperPlayback_t playback)
1600{
1601 DVR_WrapperCtx_t *ctx;
1602 int error;
1603
1604 DVR_RETURN_IF_FALSE(playback);
1605
1606 ctx = ctx_getPlayback((unsigned long)playback);
1607 DVR_RETURN_IF_FALSE(ctx);
1608
Gong Kefdb31922022-06-17 17:11:16 +08001609 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001610 DVR_WRAPPER_INFO("close playback(sn:%ld)\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001611 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001612
1613 if (ctx->playback.param_open.is_timeshift)
1614 sn_timeshift_playback = 0;
1615
1616 /*try stop first*/
wentao.maa210e5e2022-10-12 16:10:03 +08001617 dvr_playback_stop(ctx->playback.player, DVR_TRUE);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001618
1619 {
1620 /*remove all segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08001621 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001622
Wentao MA270dc0f2022-08-23 13:17:26 +08001623 list_for_each_entry(p_seg, &ctx->segments, head) {
1624 error = dvr_playback_remove_segment(ctx->playback.player, p_seg->playback_info.segment_id);
Wentao MA96f68962022-06-15 19:45:35 +08001625 DVR_WRAPPER_INFO("playback(sn:%ld) remove seg(%lld) (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08001626 ctx->sn, p_seg->playback_info.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001627 }
1628 ctx_freeSegments(ctx);
1629 }
1630
1631 error = dvr_playback_close(ctx->playback.player);
1632
Wentao MA96f68962022-06-15 19:45:35 +08001633 DVR_WRAPPER_INFO("playback(sn:%ld) closed.\n", ctx->sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001634 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001635 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001636
1637 wrapper_releaseThreadForType(ctx->type);
1638
1639 return error;
1640}
1641
1642int dvr_wrapper_start_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackFlag_t flags, DVR_PlaybackPids_t *p_pids)
1643{
1644 DVR_WrapperCtx_t *ctx;
Wentao MA9aa0aa02021-12-23 18:30:17 +08001645 int error=0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001646 uint64_t *p_segment_ids;
1647 uint32_t segment_nb;
1648 uint32_t i;
1649 DVR_RecordSegmentInfo_t seg_info_1st;
Wentao MA9aa0aa02021-12-23 18:30:17 +08001650 int got_1st_seg=0;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001651 DVR_WrapperCtx_t *ctx_record;/*for timeshift*/
hualing chenc110f952021-01-18 11:25:37 +08001652 DVR_Bool_t is_timeshift = DVR_FALSE;
wentao.maf57dd232022-10-08 16:07:29 +08001653 DVR_PlaybackSegmentFlag_t segflags = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001654
1655 DVR_RETURN_IF_FALSE(playback);
1656 DVR_RETURN_IF_FALSE(p_pids);
1657
hualing chenc110f952021-01-18 11:25:37 +08001658 ctx_record = NULL;
1659
1660 /*lock the recorder to avoid changing the recording segments*/
1661 ctx_record = ctx_getRecord(sn_timeshift_record);
1662
1663 if (ctx_record) {
Gong Kefdb31922022-06-17 17:11:16 +08001664 wrapper_mutex_lock(&ctx_record->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001665 if (!ctx_valid(ctx_record)
1666 || ctx_record->sn != sn_timeshift_record) {
Wentao MA96f68962022-06-15 19:45:35 +08001667 DVR_WRAPPER_INFO("timeshift, record is not for timeshifting, FATAL error found\n");
Gong Kefdb31922022-06-17 17:11:16 +08001668 wrapper_mutex_unlock(&ctx_record->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001669 is_timeshift = DVR_FALSE;
1670 } else {
1671 is_timeshift = DVR_TRUE;
1672 }
1673 }
1674
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001675 ctx = ctx_getPlayback((unsigned long)playback);
1676 DVR_RETURN_IF_FALSE(ctx);
1677
Gong Kefdb31922022-06-17 17:11:16 +08001678 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001679
Wentao MA96f68962022-06-15 19:45:35 +08001680 DVR_WRAPPER_INFO("start playback(sn:%ld) (%s)\n\t flags(0x%x) v/a/ad/sub/pcr(%d:%d %d:%d %d:%d %d:%d %d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001681 ctx->sn,
1682 ctx->playback.param_open.location,
1683 flags,
1684 p_pids->video.pid, p_pids->video.format,
1685 p_pids->audio.pid, p_pids->audio.format,
1686 p_pids->ad.pid, p_pids->ad.format,
1687 p_pids->subtitle.pid, p_pids->subtitle.format,
1688 p_pids->pcr.pid);
1689
Gong Kefdb31922022-06-17 17:11:16 +08001690 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001691
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001692 if (ctx->playback.param_open.is_timeshift) {
1693 /*lock the recorder to avoid changing the recording segments*/
hualing chenc110f952021-01-18 11:25:37 +08001694 if (is_timeshift == DVR_FALSE) {
Wentao MA96f68962022-06-15 19:45:35 +08001695 DVR_WRAPPER_INFO("timeshift, record is not for timeshifting, FATAL error return\n");
Gong Kefdb31922022-06-17 17:11:16 +08001696 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001697 return DVR_FAILURE;
1698 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001699 DVR_WRAPPER_INFO("playback(sn:%ld) record(sn:%ld) locked ok due to timeshift\n",
hualing chenc110f952021-01-18 11:25:37 +08001700 ctx->sn, ctx_record->sn);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001701 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001702 }
1703
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001704 /*obtain all segments in a list*/
1705 segment_nb = 0;
1706 p_segment_ids = NULL;
1707 error = dvr_segment_get_list(ctx->playback.param_open.location, &segment_nb, &p_segment_ids);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001708 if (!error) {
1709 got_1st_seg = 0;
hualing chenb9a02922021-12-14 11:29:47 +08001710 struct list_head info_list; /**< segment list head*/
1711 INIT_LIST_HEAD(&info_list);
1712
Wentao MA96f68962022-06-15 19:45:35 +08001713 DVR_WRAPPER_INFO("get list segment_nb::%d",segment_nb);
hualing chenb9a02922021-12-14 11:29:47 +08001714 //we need free info list buf when we used end.
1715 error = dvr_segment_get_allInfo(ctx->playback.param_open.location, &info_list);
hualing chen926a8ec2021-12-20 20:38:24 +08001716 if (error == DVR_FAILURE) {
hualing chenb9a02922021-12-14 11:29:47 +08001717 error = DVR_FAILURE;
Zhiqiang Handc3bfe52022-07-07 10:48:39 +08001718 DVR_WRAPPER_INFO("fail to get all seg info (location:%s), (error:%d)\n",
1719 ctx->playback.param_open.location, error);
wentao.maf57dd232022-10-08 16:07:29 +08001720 // Tainted data issue originating from fgets seem false positive, so we
1721 // just suppress it here.
1722 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08001723 for (i = 0; i < segment_nb; i++) {
1724 DVR_RecordSegmentInfo_t seg_info;
Wentao MA4d85ff32022-09-23 11:36:18 +08001725 memset((void*)&seg_info,0,sizeof(seg_info));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001726
hualing chenb9a02922021-12-14 11:29:47 +08001727 error = dvr_segment_get_info(ctx->playback.param_open.location, p_segment_ids[i], &seg_info);
1728 if (error) {
1729 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08001730 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chenb9a02922021-12-14 11:29:47 +08001731 ctx->playback.param_open.location, p_segment_ids[i], error);
1732 break;
1733 }
1734 //add check if has audio or video pid. if not exist. not add segment to playback
1735 int ii = 0;
1736 int has_av = 0;
wentao.maf57dd232022-10-08 16:07:29 +08001737 // Tainted data issue originating from fgets seem false positive, so we
1738 // just suppress it here.
1739 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08001740 for (ii = 0; ii < seg_info.nb_pids; ii++) {
1741 int type = (seg_info.pids[ii].type >> 24) & 0x0f;
1742 if (type == DVR_STREAM_TYPE_VIDEO ||
1743 type == DVR_STREAM_TYPE_AUDIO ||
1744 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001745 DVR_WRAPPER_INFO("success to get seg av info \n");
1746 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 +08001747 DVR_STREAM_TYPE_VIDEO,
1748 DVR_STREAM_TYPE_AUDIO,
1749 DVR_STREAM_TYPE_AD);
1750 has_av = 1;
1751 //break;
1752 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001753 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 +08001754 DVR_STREAM_TYPE_VIDEO,
1755 DVR_STREAM_TYPE_AUDIO,
1756 DVR_STREAM_TYPE_AD);
1757 }
1758 }
1759 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001760 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001761 continue;
1762 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001763 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001764 }
Wentao MA9628de82022-09-13 14:19:37 +08001765 segflags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
1766 error = wrapper_addPlaybackSegment(ctx, &seg_info, p_pids, segflags);
wentao.maa210e5e2022-10-12 16:10:03 +08001767 if (error == DVR_FAILURE) {
1768 DVR_WRAPPER_WARN("adding playback segment fails");
hualing chenb9a02922021-12-14 11:29:47 +08001769 break;
wentao.maa210e5e2022-10-12 16:10:03 +08001770 }
hualing chenb9a02922021-12-14 11:29:47 +08001771 /*copy the 1st segment*/
1772 if (got_1st_seg == 0) {
1773 seg_info_1st = seg_info;
1774 got_1st_seg = 1;
1775 }
1776 }
1777 } else {
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 (i = 0; i < segment_nb; i++) {
Wentao MA4d85ff32022-09-23 11:36:18 +08001782 DVR_RecordSegmentInfo_t *p_seg_info;
hualing chenb9a02922021-12-14 11:29:47 +08001783 int found = 0;
Wentao MA4d85ff32022-09-23 11:36:18 +08001784 list_for_each_entry(p_seg_info, &info_list, head)
hualing chenb9a02922021-12-14 11:29:47 +08001785 {
Wentao MA4d85ff32022-09-23 11:36:18 +08001786 if (p_seg_info->id == p_segment_ids[i]) {
hualing chenb9a02922021-12-14 11:29:47 +08001787 found = 1;
Wentao MA96f68962022-06-15 19:45:35 +08001788 DVR_WRAPPER_INFO("get segment info::%d", i);
hualing chenb9a02922021-12-14 11:29:47 +08001789 break;
1790 }
1791 }
1792 if (!found) {
hualing chen8aed9582021-12-24 17:59:56 +08001793 //last info is not found if when recording occured power off.
1794 if (p_segment_ids[i] == segment_nb - 1) {
1795 DVR_RecordSegmentInfo_t seg_info;
Wentao MA4d85ff32022-09-23 11:36:18 +08001796 memset((void*)&seg_info,0,sizeof(seg_info));
hualing chen8aed9582021-12-24 17:59:56 +08001797
1798 error = dvr_segment_get_info(ctx->playback.param_open.location, p_segment_ids[i], &seg_info);
1799 if (error) {
1800 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08001801 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chen8aed9582021-12-24 17:59:56 +08001802 ctx->playback.param_open.location, p_segment_ids[i], error);
1803 break;
1804 }
1805 //
1806 //add check if has audio or video pid. if not exist. not add segment to playback
1807 int ii = 0;
1808 int has_av = 0;
wentao.maf57dd232022-10-08 16:07:29 +08001809 // Tainted data issue originating from fgets seem false positive, so we
1810 // just suppress it here.
1811 // coverity[tainted_data]
hualing chen8aed9582021-12-24 17:59:56 +08001812 for (ii = 0; ii < seg_info.nb_pids; ii++) {
1813 int type = (seg_info.pids[ii].type >> 24) & 0x0f;
1814 if (type == DVR_STREAM_TYPE_VIDEO ||
1815 type == DVR_STREAM_TYPE_AUDIO ||
1816 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001817 DVR_WRAPPER_INFO("success to get seg av info \n");
1818 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 +08001819 DVR_STREAM_TYPE_VIDEO,
1820 DVR_STREAM_TYPE_AUDIO,
1821 DVR_STREAM_TYPE_AD);
1822 has_av = 1;
1823 //break;
1824 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001825 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 +08001826 DVR_STREAM_TYPE_VIDEO,
1827 DVR_STREAM_TYPE_AUDIO,
1828 DVR_STREAM_TYPE_AD);
1829 }
1830 }
1831 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001832 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chen8aed9582021-12-24 17:59:56 +08001833 continue;
1834 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001835 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chen8aed9582021-12-24 17:59:56 +08001836 }
Wentao MA9628de82022-09-13 14:19:37 +08001837 segflags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
1838 error = wrapper_addPlaybackSegment(ctx, &seg_info, p_pids, segflags);
wentao.maa210e5e2022-10-12 16:10:03 +08001839 if (error == DVR_FAILURE) {
1840 DVR_WRAPPER_WARN("adding playback segment fails");
hualing chen8aed9582021-12-24 17:59:56 +08001841 break;
wentao.maa210e5e2022-10-12 16:10:03 +08001842 }
hualing chen8aed9582021-12-24 17:59:56 +08001843 }
hualing chenb9a02922021-12-14 11:29:47 +08001844 continue;
1845 }
1846
1847 //add check if has audio or video pid. if not exist. not add segment to playback
1848 int ii = 0;
1849 int has_av = 0;
Wentao MA4d85ff32022-09-23 11:36:18 +08001850 for (ii = 0; ii < p_seg_info->nb_pids; ii++) {
1851 int type = (p_seg_info->pids[ii].type >> 24) & 0x0f;
hualing chenb9a02922021-12-14 11:29:47 +08001852 if (type == DVR_STREAM_TYPE_VIDEO ||
1853 type == DVR_STREAM_TYPE_AUDIO ||
1854 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001855 DVR_WRAPPER_INFO("success to get seg av info \n");
Wentao MA4d85ff32022-09-23 11:36:18 +08001856 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 +08001857 DVR_STREAM_TYPE_VIDEO,
1858 DVR_STREAM_TYPE_AUDIO,
1859 DVR_STREAM_TYPE_AD);
1860 has_av = 1;
1861 //break;
1862 } else {
Wentao MA4d85ff32022-09-23 11:36:18 +08001863 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 +08001864 DVR_STREAM_TYPE_VIDEO,
1865 DVR_STREAM_TYPE_AUDIO,
1866 DVR_STREAM_TYPE_AD);
1867 }
1868 }
1869 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001870 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001871 continue;
1872 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001873 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001874 }
Wentao MA9628de82022-09-13 14:19:37 +08001875 segflags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
Wentao MA4d85ff32022-09-23 11:36:18 +08001876 error = wrapper_addPlaybackSegment(ctx, p_seg_info, p_pids, segflags);
wentao.maa210e5e2022-10-12 16:10:03 +08001877 if (error == DVR_FAILURE) {
1878 DVR_WRAPPER_WARN("adding playback segment fails");
hualing chenb9a02922021-12-14 11:29:47 +08001879 break;
wentao.maa210e5e2022-10-12 16:10:03 +08001880 }
hualing chenb9a02922021-12-14 11:29:47 +08001881
1882 /*copy the 1st segment*/
1883 if (got_1st_seg == 0) {
Wentao MA4d85ff32022-09-23 11:36:18 +08001884 seg_info_1st = *p_seg_info;
hualing chenb9a02922021-12-14 11:29:47 +08001885 got_1st_seg = 1;
1886 }
hualing chen92f3a142020-07-08 20:59:33 +08001887 }
hualing chenb9a02922021-12-14 11:29:47 +08001888 //free list
1889 DVR_RecordSegmentInfo_t *segment = NULL;
1890 DVR_RecordSegmentInfo_t *segment_tmp = NULL;
1891 list_for_each_entry_safe(segment, segment_tmp, &info_list, head)
1892 {
1893 if (segment) {
1894 list_del(&segment->head);
1895 free(segment);
1896 }
1897 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001898 }
hualing chenb9a02922021-12-14 11:29:47 +08001899
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001900 free(p_segment_ids);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001901
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001902 /* return if no segment or fail to add */
1903 if (!error && got_1st_seg) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001904
Wentao MA270dc0f2022-08-23 13:17:26 +08001905 /*copy the obsolete information, must for timeshifting*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001906 if (ctx->playback.param_open.is_timeshift && ctx_record) {
1907 ctx->playback.obsolete = ctx_record->record.obsolete;
1908 }
1909
Wentao MA96f68962022-06-15 19:45:35 +08001910 DVR_WRAPPER_INFO("playback(sn:%ld) (%d) segments added\n", ctx->sn, i);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001911
1912 ctx->playback.reach_end = DVR_FALSE;
1913 if ((flags&DVR_PLAYBACK_STARTED_PAUSEDLIVE) == DVR_PLAYBACK_STARTED_PAUSEDLIVE)
1914 ctx->playback.speed = 0.0f;
1915 else
1916 ctx->playback.speed = 100.0f;
1917
1918 ctx->playback.pids_req = *p_pids;
Wentao MA270dc0f2022-08-23 13:17:26 +08001919 //calculate segment id and pos
hualing chen03fd4942021-07-15 15:56:41 +08001920 if (dvr_playback_check_limit(ctx->playback.player)) {
Gong Kefdb31922022-06-17 17:11:16 +08001921 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001922 dvr_wrapper_seek_playback(playback, 0);
Gong Kefdb31922022-06-17 17:11:16 +08001923 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001924 error = dvr_playback_start(ctx->playback.player, flags);
1925 } else {
wentao.maa210e5e2022-10-12 16:10:03 +08001926 dvr_playback_seek(ctx->playback.player, seg_info_1st.id, 0);
hualing chen03fd4942021-07-15 15:56:41 +08001927 error = dvr_playback_start(ctx->playback.player, flags);
Wentao MA96f68962022-06-15 19:45:35 +08001928 DVR_WRAPPER_INFO("playback(sn:%ld) seek(seg:%llu 0) for start (%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08001929 ctx->sn, seg_info_1st.id, error);
1930 }
Wentao MA96f68962022-06-15 19:45:35 +08001931 DVR_WRAPPER_INFO("playback(sn:%ld) started (%d)\n", ctx->sn, error);
hualing chen451c8f72022-03-09 13:05:52 +08001932 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001933 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 +08001934 }
1935 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001936
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001937 if (ctx->playback.param_open.is_timeshift) {
1938 /*unlock the recorder locked above*/
1939 if (ctx_record && ctx_valid(ctx_record)) {
Gong Kefdb31922022-06-17 17:11:16 +08001940 wrapper_mutex_unlock(&ctx_record->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001941 DVR_WRAPPER_INFO("playback(sn:%ld), record(sn:%ld) unlocked ok due to timeshift\n",
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001942 ctx->sn, ctx_record->sn);
1943 }
1944 }
Gong Kefdb31922022-06-17 17:11:16 +08001945 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001946
1947 return error;
1948}
hualing chen002e5b92022-02-23 17:51:21 +08001949//stop record and playback
1950int dvr_wrapper_stop_timeshift (DVR_WrapperPlayback_t playback)
1951{
1952 DVR_WrapperCtx_t *ctx_record = NULL;/*for timeshift*/
1953 int error;
Wentao MA96f68962022-06-15 19:45:35 +08001954 DVR_WRAPPER_INFO("stop timeshift record\n");
hualing chen002e5b92022-02-23 17:51:21 +08001955
1956 //stop timeshift record
1957 ctx_record = ctx_getRecord(sn_timeshift_record);
wentao.maa210e5e2022-10-12 16:10:03 +08001958 dvr_wrapper_stop_record((DVR_WrapperRecord_t)sn_timeshift_record);
hualing chen002e5b92022-02-23 17:51:21 +08001959
Wentao MA96f68962022-06-15 19:45:35 +08001960 DVR_WRAPPER_INFO("stop timeshift ...stop play\n");
hualing chen002e5b92022-02-23 17:51:21 +08001961 //stop play
1962 error = dvr_wrapper_stop_playback(playback);
1963 //del timeshift file
1964 if (ctx_record != NULL) {
Wentao MA96f68962022-06-15 19:45:35 +08001965 DVR_WRAPPER_INFO("del timeshift(sn:%ld) ...3\n", ctx_record->sn);
hualing chen002e5b92022-02-23 17:51:21 +08001966 error = dvr_segment_del_by_location(ctx_record->record.param_open.location);
1967 }
1968 return error;
1969}
1970//start record and start playback
1971int dvr_wrapper_restart_timeshift(DVR_WrapperPlayback_t playback, DVR_PlaybackFlag_t flags, DVR_PlaybackPids_t *p_pids)
1972{
1973 DVR_WrapperCtx_t *ctx;
1974 DVR_RecordStartParams_t *start_param;
1975 int error;
1976
1977 ctx = ctx_getRecord((unsigned long)sn_timeshift_record);
1978 DVR_RETURN_IF_FALSE(ctx);
1979
Gong Kefdb31922022-06-17 17:11:16 +08001980 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001981 DVR_WRAPPER_INFO("restart record(sn:%ld, location:%s)...\n", ctx->sn, ctx->record.param_open.location);
Gong Kefdb31922022-06-17 17:11:16 +08001982 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen002e5b92022-02-23 17:51:21 +08001983
hualing chen451c8f72022-03-09 13:05:52 +08001984 {
1985 //clear old record status
1986 // struct {
1987 // DVR_WrapperRecordOpenParams_t param_open;
1988 // DVR_RecordStartParams_t param_start;
1989 // DVR_RecordStartParams_t param_update;
1990 // DVR_RecordHandle_t recorder;
1991 // DVR_RecordEventFunction_t event_fn;
1992 // void *event_userdata;
1993
1994 // /*total status = seg_status + status + obsolete*/
1995 // DVR_RecordStatus_t seg_status; /**<status of current segment*/
1996 // DVR_WrapperRecordStatus_t status; /**<status of remaining segments*/
1997 // uint64_t next_segment_id;
1998
1999 // DVR_WrapperInfo_t obsolete; /**<data obsolete due to the max limit*/
2000 // } record;
2001 memset(&(ctx->record.seg_status), 0, sizeof(DVR_RecordStatus_t));
2002 memset(&(ctx->record.status), 0, sizeof(DVR_WrapperRecordStatus_t));
2003 memset(&(ctx->record.obsolete), 0, sizeof(DVR_WrapperInfo_t));
2004 }
2005
hualing chen002e5b92022-02-23 17:51:21 +08002006 start_param = &ctx->record.param_start;
2007
2008 error = dvr_record_start_segment(ctx->record.recorder, start_param);
2009 {
2010 DVR_RecordSegmentInfo_t new_seg_info =
2011 { .id = start_param->segment.segment_id, };
2012 wrapper_addRecordSegment(ctx, &new_seg_info);
Wentao MA96f68962022-06-15 19:45:35 +08002013 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 +08002014 ctx->record.next_segment_id = start_param->segment.segment_id + 1;
2015 DVR_RecordStartParams_t *update_param;
2016 update_param = &ctx->record.param_update;
2017 memcpy(update_param, start_param, sizeof(*update_param));
2018 int i = 0;
2019 for (i = 0; i < update_param->segment.nb_pids; i++)
2020 update_param->segment.pid_action[i] = DVR_RECORD_PID_KEEP;
hualing chen002e5b92022-02-23 17:51:21 +08002021 }
2022
Wentao MA96f68962022-06-15 19:45:35 +08002023 DVR_WRAPPER_INFO("re record(sn:%ld) started = (%d)\n", ctx->sn, error);
hualing chen002e5b92022-02-23 17:51:21 +08002024
Gong Kefdb31922022-06-17 17:11:16 +08002025 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen002e5b92022-02-23 17:51:21 +08002026
2027 //start play
Wentao MA96f68962022-06-15 19:45:35 +08002028 DVR_WRAPPER_INFO("re start play and clear old status\n");
hualing chen451c8f72022-03-09 13:05:52 +08002029 //clear play statue
2030 ctx = ctx_getPlayback((unsigned long)playback);
2031 if (ctx) {
Wentao MA4d85ff32022-09-23 11:36:18 +08002032 //reset old playback status
hualing chen451c8f72022-03-09 13:05:52 +08002033 // struct {
2034 // DVR_WrapperPlaybackOpenParams_t param_open;
2035 // DVR_PlaybackHandle_t player;
2036 // DVR_PlaybackEventFunction_t event_fn;
2037 // void *event_userdata;
2038
2039 // /*total status = seg_status + status*/
2040 // DVR_PlaybackStatus_t seg_status;
2041 // DVR_WrapperPlaybackStatus_t status;
2042 // DVR_PlaybackPids_t pids_req;
2043 // DVR_PlaybackEvent_t last_event;
2044 // float speed;
2045 // DVR_Bool_t reach_end;
2046
2047 // DVR_WrapperInfo_t obsolete;
2048 // DVR_Bool_t tf_full;
2049 // } playback;
Wentao MA4d85ff32022-09-23 11:36:18 +08002050 ctx->playback.tf_full = DVR_FALSE;
2051 ctx->playback.reach_end = DVR_FALSE;
hualing chen451c8f72022-03-09 13:05:52 +08002052 memset(&(ctx->playback.last_event), 0, sizeof(DVR_PlaybackEvent_t));
2053 memset(&(ctx->playback.seg_status), 0, sizeof(DVR_PlaybackStatus_t));
2054 memset(&(ctx->playback.status), 0, sizeof(DVR_WrapperPlaybackStatus_t));
2055 memset(&(ctx->playback.obsolete), 0, sizeof(DVR_WrapperInfo_t));
2056 }
hualing chen002e5b92022-02-23 17:51:21 +08002057 error = dvr_wrapper_start_playback(playback, flags, p_pids);
2058 return error;
2059}
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002060
2061int dvr_wrapper_stop_playback (DVR_WrapperPlayback_t playback)
2062{
2063 DVR_WrapperCtx_t *ctx;
2064 int error;
2065
2066 DVR_RETURN_IF_FALSE(playback);
2067
2068 ctx = ctx_getPlayback((unsigned long)playback);
2069 DVR_RETURN_IF_FALSE(ctx);
2070
Gong Kefdb31922022-06-17 17:11:16 +08002071 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08002072 DVR_WRAPPER_INFO("stop playback(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002073 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002074
2075 error = dvr_playback_stop(ctx->playback.player, DVR_TRUE);
2076
2077 {
2078 /*remove all segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002079 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002080
Wentao MA270dc0f2022-08-23 13:17:26 +08002081 list_for_each_entry(p_seg, &ctx->segments, head) {
2082 error = dvr_playback_remove_segment(ctx->playback.player, p_seg->playback_info.segment_id);
Wentao MA96f68962022-06-15 19:45:35 +08002083 DVR_WRAPPER_INFO("playback(sn:%ld) remove seg(%lld) (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08002084 ctx->sn, p_seg->playback_info.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002085 }
2086 ctx_freeSegments(ctx);
2087 }
2088
Wentao MA96f68962022-06-15 19:45:35 +08002089 DVR_WRAPPER_INFO("playback(sn:%ld) stopped (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002090 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002091
2092 return error;
2093}
2094
2095int dvr_wrapper_pause_playback (DVR_WrapperPlayback_t playback)
2096{
2097 DVR_WrapperCtx_t *ctx;
2098 int error;
2099
2100 DVR_RETURN_IF_FALSE(playback);
2101
2102 ctx = ctx_getPlayback((unsigned long)playback);
2103 DVR_RETURN_IF_FALSE(ctx);
2104
Gong Kefdb31922022-06-17 17:11:16 +08002105 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08002106 DVR_WRAPPER_INFO("pause playback(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002107 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen36e0dfd2020-05-02 16:33:06 +08002108 //clear end event
Zhiqiang Hanb723cdb2020-05-09 11:10:29 +08002109 if (ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_END)
hualing chen36e0dfd2020-05-02 16:33:06 +08002110 ctx->playback.last_event = DVR_PLAYBACK_EVENT_TRANSITION_OK;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002111
2112 error = dvr_playback_pause(ctx->playback.player, DVR_FALSE);
2113
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002114 ctx->playback.speed = 0.0f;
2115
Wentao MA96f68962022-06-15 19:45:35 +08002116 DVR_WRAPPER_INFO("playback(sn:%ld) paused (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002117 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002118
2119 return error;
2120}
2121
2122int dvr_wrapper_resume_playback (DVR_WrapperPlayback_t playback)
2123{
2124 DVR_WrapperCtx_t *ctx;
2125 int error;
2126
2127 DVR_RETURN_IF_FALSE(playback);
2128
2129 ctx = ctx_getPlayback((unsigned long)playback);
2130 DVR_RETURN_IF_FALSE(ctx);
hualing chen03fd4942021-07-15 15:56:41 +08002131 //if set limit.we need check if seek to valid data when resume
2132 uint32_t time_offset = ctx->playback.status.info_cur.time + ctx->playback.status.info_obsolete.time;
2133 if (dvr_playback_check_limit(ctx->playback.player)) {
2134 int expired = dvr_playback_calculate_expiredlen(ctx->playback.player);
2135 if (expired > time_offset) {
Wentao MA96f68962022-06-15 19:45:35 +08002136 DVR_WRAPPER_INFO("seek before resume reset offset playback(sn:%ld) (off:%d expired:%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08002137 ctx->sn, time_offset, expired);
2138 time_offset = expired;
2139 dvr_wrapper_seek_playback(playback, time_offset);
2140 }
2141 }
Gong Kefdb31922022-06-17 17:11:16 +08002142 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08002143 DVR_WRAPPER_INFO("resume playback(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002144 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002145
2146 error = dvr_playback_resume(ctx->playback.player);
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002147 ctx->playback.speed = 100.0f;
2148
Wentao MA96f68962022-06-15 19:45:35 +08002149 DVR_WRAPPER_INFO("playback(sn:%ld) resumed (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002150 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002151
2152 return error;
2153}
2154
2155int dvr_wrapper_set_playback_speed (DVR_WrapperPlayback_t playback, float speed)
2156{
2157 DVR_WrapperCtx_t *ctx;
2158 int error;
2159 DVR_PlaybackSpeed_t dvr_speed = {
2160 .speed = { speed },
2161 .mode = (speed > 0) ? DVR_PLAYBACK_FAST_FORWARD : DVR_PLAYBACK_FAST_BACKWARD
2162 };
2163
2164 DVR_RETURN_IF_FALSE(playback);
2165
2166 ctx = ctx_getPlayback((unsigned long)playback);
2167 DVR_RETURN_IF_FALSE(ctx);
2168
Gong Kefdb31922022-06-17 17:11:16 +08002169 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08002170 DVR_WRAPPER_INFO("speed playback(sn:%ld) (x%f) .(x%f)..\n", ctx->sn, speed, ctx->playback.speed);
Gong Kefdb31922022-06-17 17:11:16 +08002171 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002172
2173 error = dvr_playback_set_speed(ctx->playback.player, dvr_speed);
2174
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002175 if (ctx->playback.speed != 0.0f && ctx->playback.speed != 100.0f
2176 && ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_BEGIN
2177 && ctx->playback.seg_status.state == DVR_PLAYBACK_STATE_PAUSE) {
Wentao MA96f68962022-06-15 19:45:35 +08002178 DVR_WRAPPER_INFO("x%f -> x%f, paused, do resume first\n", ctx->playback.speed, speed);
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002179 error = dvr_playback_resume(ctx->playback.player);
2180 } else if (ctx->playback.speed == 0.0f
2181 && speed != 0.0f
2182 && speed != 100.0f) {
2183 /*libdvr do not support pause with speed=0, will not be here*/
Wentao MA96f68962022-06-15 19:45:35 +08002184 DVR_WRAPPER_INFO("x%f -> x%f, do resume first\n", ctx->playback.speed, speed);
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002185 error = dvr_playback_resume(ctx->playback.player);
2186 }
2187
2188 ctx->playback.speed = speed;
2189
Wentao MA96f68962022-06-15 19:45:35 +08002190 DVR_WRAPPER_INFO("playback(sn:%ld) speeded(x%f) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002191 ctx->sn, speed, error);
Gong Kefdb31922022-06-17 17:11:16 +08002192 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002193
2194 return error;
2195}
2196
hualing chen03fd4942021-07-15 15:56:41 +08002197int dvr_wrapper_setlimit_playback (DVR_WrapperPlayback_t playback, uint64_t time, int32_t limit)
2198{
2199 DVR_WrapperCtx_t *ctx;
2200 int error;
2201
2202 DVR_RETURN_IF_FALSE(playback);
2203
2204 ctx = ctx_getPlayback((unsigned long)playback);
2205 DVR_RETURN_IF_FALSE(ctx);
2206
Gong Kefdb31922022-06-17 17:11:16 +08002207 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002208
Wentao MAe8ba5172022-08-09 11:18:17 +08002209 DVR_WRAPPER_INFO("set_limit playback(sn:%ld) (time:%lld limit:%d) ...\n", ctx->sn, time, limit);
Gong Kefdb31922022-06-17 17:11:16 +08002210 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002211
2212 error = dvr_playback_setlimit(ctx->playback.player, time, limit);
Wentao MAe8ba5172022-08-09 11:18:17 +08002213 DVR_WRAPPER_INFO("playback(sn:%ld) set_limit(time:%lld limit:%d) ...\n", ctx->sn, time, limit);
hualing chen03fd4942021-07-15 15:56:41 +08002214
Gong Kefdb31922022-06-17 17:11:16 +08002215 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002216
2217 return error;
2218}
2219
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002220int dvr_wrapper_seek_playback (DVR_WrapperPlayback_t playback, uint32_t time_offset)
2221{
2222 DVR_WrapperCtx_t *ctx;
2223 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08002224 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002225 uint64_t segment_id;
2226 uint32_t off;
2227 uint64_t last_segment_id;
2228 uint32_t pre_off;
2229
2230 DVR_RETURN_IF_FALSE(playback);
2231
2232 ctx = ctx_getPlayback((unsigned long)playback);
2233 DVR_RETURN_IF_FALSE(ctx);
2234
Gong Kefdb31922022-06-17 17:11:16 +08002235 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002236
Wentao MA96f68962022-06-15 19:45:35 +08002237 DVR_WRAPPER_INFO("seek playback(sn:%ld) (off:%d) ...\n", ctx->sn, time_offset);
Gong Kefdb31922022-06-17 17:11:16 +08002238 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002239
2240 off = 0;
2241 segment_id = 0;
2242 pre_off = 0;
2243 last_segment_id = 0;
2244
hualing chen03fd4942021-07-15 15:56:41 +08002245 //if set limit info we need check ts data is
2246 //expired when seek
2247 if (dvr_playback_check_limit(ctx->playback.player)) {
2248 int expired = dvr_playback_calculate_expiredlen(ctx->playback.player);
2249 if (expired > time_offset) {
Wentao MA96f68962022-06-15 19:45:35 +08002250 DVR_WRAPPER_INFO("seek reset offset playback(sn:%ld) (off:%d expired:%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08002251 ctx->sn, time_offset, expired);
2252 time_offset = expired;
2253 }
2254 }
2255
Wentao MA270dc0f2022-08-23 13:17:26 +08002256 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
2257 segment_id = p_seg->seg_info.id;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002258
Wentao MA270dc0f2022-08-23 13:17:26 +08002259 if ((ctx->playback.obsolete.time + pre_off + p_seg->seg_info.duration) > time_offset)
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002260 break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002261
Wentao MA270dc0f2022-08-23 13:17:26 +08002262 last_segment_id = p_seg->seg_info.id;
2263 pre_off += p_seg->seg_info.duration;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002264 }
2265
2266 if (last_segment_id == segment_id) {
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002267 /*1.only one seg with id:0, 2.offset exceeds the total duration*/
2268 off = time_offset;
2269 } else if (ctx->playback.obsolete.time >= time_offset) {
2270 off = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002271 } else {
hualing chenda76fc52020-05-28 14:56:42 +08002272 off = time_offset - pre_off - ctx->playback.obsolete.time;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002273 }
2274
Wentao MA96f68962022-06-15 19:45:35 +08002275 DVR_WRAPPER_INFO("seek playback(sn:%ld) (seg:%lld, off:%d)\n",
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002276 ctx->sn, segment_id, off);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002277 error = dvr_playback_seek(ctx->playback.player, segment_id, off);
Wentao MA96f68962022-06-15 19:45:35 +08002278 DVR_WRAPPER_INFO("playback(sn:%ld) seeked(off:%d) (%d)\n", ctx->sn, time_offset, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002279
Gong Kefdb31922022-06-17 17:11:16 +08002280 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002281
2282 return error;
2283}
2284
2285int dvr_wrapper_update_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackPids_t *p_pids)
2286{
2287 DVR_WrapperCtx_t *ctx;
2288 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08002289 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002290
2291 DVR_RETURN_IF_FALSE(playback);
2292 DVR_RETURN_IF_FALSE(p_pids);
2293
2294 ctx = ctx_getPlayback((unsigned long)playback);
2295 DVR_RETURN_IF_FALSE(ctx);
2296
Gong Kefdb31922022-06-17 17:11:16 +08002297 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002298
Wentao MA96f68962022-06-15 19:45:35 +08002299 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) ...\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002300 ctx->sn,
2301 p_pids->video.pid, p_pids->video.format,
2302 p_pids->audio.pid, p_pids->audio.format);
Gong Kefdb31922022-06-17 17:11:16 +08002303 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002304
2305 ctx->playback.pids_req = *p_pids;
2306
2307 error = 0;
Wentao MA270dc0f2022-08-23 13:17:26 +08002308 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002309 /*should update the whole list of segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002310 /*if (p_seg->seg_info.id == ctx->current_segment_id)*/ {
2311 /*list_for_each_entry_from(p_seg, &ctx->segments, head)*/ {
2312 /*check update for pids*/
2313 if (memcmp(&p_seg->playback_info.pids, p_pids, sizeof(*p_pids)) != 0) {
2314 p_seg->playback_info.pids = *p_pids;
2315 error = dvr_playback_update_segment_pids(ctx->playback.player, p_seg->seg_info.id, p_pids);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002316 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08002317 DVR_WRAPPER_INFO("failed to playback(sn:%ld) update segment(id:%lld) pids (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08002318 ctx->sn, p_seg->seg_info.id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002319 /*do not break, let list updated*/
2320 }
2321 }
2322 }
2323 /*break;*/
2324 }
2325 }
2326
Wentao MA96f68962022-06-15 19:45:35 +08002327 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002328 ctx->sn,
2329 p_pids->video.pid, p_pids->video.format,
2330 p_pids->audio.pid, p_pids->audio.format,
2331 error);
2332
Gong Kefdb31922022-06-17 17:11:16 +08002333 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002334
2335 return error;
2336}
2337
hualing chena5f03222021-12-02 11:22:35 +08002338int dvr_wrapper_only_update_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackPids_t *p_pids)
2339{
2340 DVR_WrapperCtx_t *ctx;
2341 int error;
Wentao MA270dc0f2022-08-23 13:17:26 +08002342 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
hualing chena5f03222021-12-02 11:22:35 +08002343
2344 DVR_RETURN_IF_FALSE(playback);
2345 DVR_RETURN_IF_FALSE(p_pids);
2346
2347 ctx = ctx_getPlayback((unsigned long)playback);
2348 DVR_RETURN_IF_FALSE(ctx);
2349
Gong Kefdb31922022-06-17 17:11:16 +08002350 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002351
Wentao MA96f68962022-06-15 19:45:35 +08002352 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) ...\n",
hualing chena5f03222021-12-02 11:22:35 +08002353 ctx->sn,
2354 p_pids->video.pid, p_pids->video.format,
2355 p_pids->audio.pid, p_pids->audio.format);
Gong Kefdb31922022-06-17 17:11:16 +08002356 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002357
2358 ctx->playback.pids_req = *p_pids;
2359
2360 error = 0;
Wentao MA270dc0f2022-08-23 13:17:26 +08002361 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
hualing chena5f03222021-12-02 11:22:35 +08002362 /*should update the whole list of segments*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002363 /*if (p_seg->seg_info.id == ctx->current_segment_id)*/ {
2364 /*list_for_each_entry_from(p_seg, &ctx->segments, head)*/ {
2365 /*check update for pids*/
2366 if (memcmp(&p_seg->playback_info.pids, p_pids, sizeof(*p_pids)) != 0) {
2367 p_seg->playback_info.pids = *p_pids;
2368 error = dvr_playback_only_update_segment_pids(ctx->playback.player, p_seg->seg_info.id, p_pids);
hualing chena5f03222021-12-02 11:22:35 +08002369 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08002370 DVR_WRAPPER_INFO("failed to playback(sn:%ld) update segment(id:%lld) pids (%d)\n",
Wentao MA270dc0f2022-08-23 13:17:26 +08002371 ctx->sn, p_seg->seg_info.id, error);
hualing chena5f03222021-12-02 11:22:35 +08002372 /*do not break, let list updated*/
2373 }
2374 }
2375 }
2376 /*break;*/
2377 }
2378 }
2379
Wentao MA96f68962022-06-15 19:45:35 +08002380 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) (%d)\n",
hualing chena5f03222021-12-02 11:22:35 +08002381 ctx->sn,
2382 p_pids->video.pid, p_pids->video.format,
2383 p_pids->audio.pid, p_pids->audio.format,
2384 error);
2385
Gong Kefdb31922022-06-17 17:11:16 +08002386 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002387
2388 return error;
2389}
2390
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002391int dvr_wrapper_get_playback_status(DVR_WrapperPlayback_t playback, DVR_WrapperPlaybackStatus_t *status)
2392{
2393 DVR_WrapperCtx_t *ctx;
2394 DVR_WrapperPlaybackStatus_t s;
2395 DVR_PlaybackStatus_t play_status;
2396 int error;
2397
2398 DVR_RETURN_IF_FALSE(playback);
2399 DVR_RETURN_IF_FALSE(status);
2400
2401 ctx = ctx_getPlayback((unsigned long)playback);
2402 DVR_RETURN_IF_FALSE(ctx);
2403
Gong Kefdb31922022-06-17 17:11:16 +08002404 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002405
Wentao MA96f68962022-06-15 19:45:35 +08002406 DVR_WRAPPER_INFO("get playback(sn:%ld) status ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002407 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002408
2409 error = dvr_playback_get_status(ctx->playback.player, &play_status);
Wentao MA96f68962022-06-15 19:45:35 +08002410 DVR_WRAPPER_INFO("playback(sn:%ld) get status (%d)\n", ctx->sn, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002411
2412 ctx->playback.seg_status = play_status;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002413 error = process_generatePlaybackStatus(ctx, &s);
2414
hualing chenb5cd42e2020-04-15 17:03:34 +08002415 if (ctx->playback.reach_end == DVR_TRUE && ctx->playback.param_open.is_timeshift == DVR_FALSE) {
2416 //reach end need set full time to cur.so app can exist playback.
Wentao MA96f68962022-06-15 19:45:35 +08002417 DVR_WRAPPER_INFO("set cur time to full time, reach end occur");
hualing chenb5cd42e2020-04-15 17:03:34 +08002418 s.info_cur.time = s.info_full.time;
2419 }
Wentao MA270dc0f2022-08-23 13:17:26 +08002420 DVR_WRAPPER_INFO("playback(sn:%ld) state/cur/full/obsolete(%d/%ld/%ld/%ld) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002421 ctx->sn,
2422 s.state,
2423 s.info_cur.time,
2424 s.info_full.time,
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002425 s.info_obsolete.time,
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002426 error);
2427
2428 *status = s;
2429
Gong Kefdb31922022-06-17 17:11:16 +08002430 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002431
2432 return error;
2433}
2434
hualing chen266b9502020-04-04 17:39:39 +08002435int dvr_wrapper_set_playback_secure_buffer (DVR_WrapperPlayback_t playback, uint8_t *p_secure_buf, uint32_t len)
2436{
2437 DVR_WrapperCtx_t *ctx;
2438 int error;
2439
2440 DVR_RETURN_IF_FALSE(playback);
2441 DVR_RETURN_IF_FALSE(p_secure_buf);
2442
2443 ctx = ctx_getPlayback((unsigned long)playback);
2444 DVR_RETURN_IF_FALSE(ctx);
2445
Gong Kefdb31922022-06-17 17:11:16 +08002446 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002447 error = dvr_playback_set_secure_buffer(ctx->playback.player, p_secure_buf, len);
Gong Kefdb31922022-06-17 17:11:16 +08002448 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002449 return error;
2450}
2451
2452int dvr_wrapper_set_playback_decrypt_callback (DVR_WrapperPlayback_t playback, DVR_CryptoFunction_t func, void *userdata)
2453{
2454 DVR_WrapperCtx_t *ctx;
2455 int error;
2456
2457 DVR_RETURN_IF_FALSE(playback);
2458 DVR_RETURN_IF_FALSE(func);
2459
2460 ctx = ctx_getPlayback((unsigned long)playback);
2461 DVR_RETURN_IF_FALSE(ctx);
2462
Gong Kefdb31922022-06-17 17:11:16 +08002463 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002464 error = dvr_playback_set_decrypt_callback(ctx->playback.player, func, userdata);
Gong Kefdb31922022-06-17 17:11:16 +08002465 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002466 return error;
2467}
2468
Zhiqiang Han620b9252021-11-09 14:23:20 +08002469int dvr_wrapper_segment_del_by_location (const char *location)
2470{
2471 char fpath[DVR_MAX_LOCATION_SIZE];
2472
2473 DVR_RETURN_IF_FALSE(location);
2474
2475 /*del the stats file*/
2476 sprintf(fpath, "%s.stats", location);
2477 unlink(fpath);
2478
2479 return dvr_segment_del_by_location(location);
2480}
2481
2482int dvr_wrapper_segment_get_info_by_location (const char *location, DVR_WrapperInfo_t *p_info)
2483{
2484 FILE *fp;
2485 char fpath[DVR_MAX_LOCATION_SIZE];
2486
2487 DVR_RETURN_IF_FALSE(location);
2488 DVR_RETURN_IF_FALSE(p_info);
2489
2490 if (p_info)
2491 memset(p_info, 0, sizeof(p_info[0]));
2492
2493 memset(fpath, 0, sizeof(fpath));
2494 sprintf(fpath, "%s.stats", location);
2495
2496 /*stats file exists*/
2497 if ((fp = fopen(fpath, "r"))) {
2498 char buf[256];
2499
2500 if (fgets(buf, sizeof(buf), fp) != NULL
2501 && (sscanf(buf, ":%llu:%lu:%u",
2502 &p_info->size,
2503 &p_info->time,
2504 &p_info->pkts) == 3)) {
2505 fclose(fp);
Wentao MA96f68962022-06-15 19:45:35 +08002506 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 +08002507 return DVR_SUCCESS;
2508 }
Zhiqiang Hanb9785922021-11-26 18:47:39 +08002509 fclose(fp);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002510 }
2511
2512 /*fallback, slow on mass files*/
Wentao MA96f68962022-06-15 19:45:35 +08002513 DVR_WRAPPER_INFO("rec '%s.stats' invalid.\n", location);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002514
2515 int error;
2516 uint32_t n_ids;
2517 uint64_t *p_ids;
Zhiqiang Han620b9252021-11-09 14:23:20 +08002518
hualing chen8aed9582021-12-24 17:59:56 +08002519 error = dvr_segment_get_list(location, &n_ids, &p_ids);
hualing chenb9a02922021-12-14 11:29:47 +08002520
Zhiqiang Han620b9252021-11-09 14:23:20 +08002521 if (!error) {
2522 int i;
hualing chenb9a02922021-12-14 11:29:47 +08002523 struct list_head info_list; /**< segment list head*/
2524 INIT_LIST_HEAD(&info_list);
2525
2526 //we need free info list buf when we used end.
hualing chen8aed9582021-12-24 17:59:56 +08002527 error = dvr_segment_get_allInfo(location, &info_list);
2528 if (error == DVR_FAILURE) {
wentao.maa210e5e2022-10-12 16:10:03 +08002529 DVR_RecordSegmentInfo_t info = { .id = 0, .nb_pids = 0,
2530 .pids = {0}, .duration = 0, .size = 0, .nb_packets = 0 };
hualing chenb9a02922021-12-14 11:29:47 +08002531
2532 memset(&info, 0, sizeof(info));
2533 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08002534 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chen8aed9582021-12-24 17:59:56 +08002535 location, 0, error);
hualing chenb9a02922021-12-14 11:29:47 +08002536
wentao.maf57dd232022-10-08 16:07:29 +08002537 // Tainted data issue originating from fgets seem false positive, so we
2538 // just suppress it here.
2539 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08002540 for (i = 0; i < n_ids; i++) {
hualing chen8aed9582021-12-24 17:59:56 +08002541 error = dvr_segment_get_info(location, p_ids[i], &info);
hualing chenb9a02922021-12-14 11:29:47 +08002542 if (!error) {
2543 p_info->size += info.size;
2544 p_info->time += info.duration;
2545 p_info->pkts += info.nb_packets;
2546 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002547 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chenb9a02922021-12-14 11:29:47 +08002548 break;
2549 }
2550 }
2551 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002552 DVR_WRAPPER_INFO("get list segment_nb::%d",n_ids);
wentao.maf57dd232022-10-08 16:07:29 +08002553 // Tainted data issue originating from fgets seem false positive, so we
2554 // just suppress it here.
2555 // coverity[tainted_data]
hualing chenb9a02922021-12-14 11:29:47 +08002556 for (i = 0; i < n_ids; i++) {
2557
2558 DVR_RecordSegmentInfo_t *seg_info;
2559 DVR_PlaybackSegmentFlag_t flags;
2560 int found = 0;
2561 list_for_each_entry(seg_info, &info_list, head)
2562 {
hualing chen8aed9582021-12-24 17:59:56 +08002563 if (seg_info->id == p_ids[i]) {
hualing chenb9a02922021-12-14 11:29:47 +08002564 found = 1;
2565 break;
2566 }
2567 }
2568 if (!found) {
Wentao MA96f68962022-06-15 19:45:35 +08002569 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 +08002570 if (p_ids[i] == n_ids - 1) {
wentao.maa210e5e2022-10-12 16:10:03 +08002571 DVR_RecordSegmentInfo_t info = { .id = 0, .nb_pids = 0,
2572 .pids = {0}, .duration = 0, .size = 0, .nb_packets = 0 };
Wentao MA96f68962022-06-15 19:45:35 +08002573 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 +08002574 error = dvr_segment_get_info(location, p_ids[i], &info);
2575 if (!error) {
2576 p_info->size += info.size;
2577 p_info->time += info.duration;
2578 p_info->pkts += info.nb_packets;
2579 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002580 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chen8aed9582021-12-24 17:59:56 +08002581 break;
2582 }
2583 }
hualing chenb9a02922021-12-14 11:29:47 +08002584 continue;
2585 }
2586
2587 if (!error) {
2588 p_info->size += seg_info->size;
2589 p_info->time += seg_info->duration;
2590 p_info->pkts += seg_info->nb_packets;
2591 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002592 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chenb9a02922021-12-14 11:29:47 +08002593 break;
2594 }
2595 }
2596 //free list
2597 DVR_RecordSegmentInfo_t *segment = NULL;
2598 DVR_RecordSegmentInfo_t *segment_tmp = NULL;
2599 list_for_each_entry_safe(segment, segment_tmp, &info_list, head)
2600 {
2601 if (segment) {
2602 list_del(&segment->head);
2603 free(segment);
2604 }
2605 }
2606 }
2607 free(p_ids);
Zhiqiang Hanb9785922021-11-26 18:47:39 +08002608 } else {
2609 n_ids = 0;
Zhiqiang Han620b9252021-11-09 14:23:20 +08002610 }
Wentao MA96f68962022-06-15 19:45:35 +08002611 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 +08002612
2613 return (error)? DVR_FAILURE : DVR_SUCCESS;
2614}
2615
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002616static DVR_Result_t wrapper_record_event_handler(DVR_RecordEvent_t event, void *params, void *userdata)
2617{
wentao.maa210e5e2022-10-12 16:10:03 +08002618 DVR_WrapperEventCtx_t evt = {
2619 .sn = (unsigned long)userdata,
2620 .type = W_REC,
2621 .record.event = event,
2622 .record.status = *(DVR_RecordStatus_t *)params
2623 };
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002624
2625 DVR_RETURN_IF_FALSE(userdata);
2626
Wentao MA96f68962022-06-15 19:45:35 +08002627 DVR_WRAPPER_INFO("evt[sn:%ld, record, evt:0x%x]\n", evt.sn, evt.record.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002628 return ctx_addRecordEvent(&evt);
2629}
2630
2631static DVR_Result_t wrapper_playback_event_handler(DVR_PlaybackEvent_t event, void *params, void *userdata)
2632{
wentao.maa210e5e2022-10-12 16:10:03 +08002633 DVR_WrapperEventCtx_t evt = {
2634 .sn = (unsigned long)userdata,
2635 .type = W_PLAYBACK,
2636 .playback.event = event,
2637 .playback.status = *(DVR_Play_Notify_t *)params
2638 };
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002639
2640 DVR_RETURN_IF_FALSE(userdata);
2641
2642 evt.sn = (unsigned long)userdata;
2643 evt.type = W_PLAYBACK;
2644 evt.playback.event = event;
2645 evt.playback.status = *(DVR_Play_Notify_t *)params;
Wentao MA9a164002022-08-29 11:20:24 +08002646 DVR_WRAPPER_INFO("evt[sn:%ld, playback, evt:0x%x]\n", evt.sn, evt.playback.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002647 return ctx_addPlaybackEvent(&evt);
2648}
2649
2650static inline int process_notifyRecord(DVR_WrapperCtx_t *ctx, DVR_RecordEvent_t evt, DVR_WrapperRecordStatus_t *status)
2651{
Wentao MA270dc0f2022-08-23 13:17:26 +08002652 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 +08002653 ctx->sn,
2654 evt,
2655 status->info.time,
2656 status->info.size,
2657 status->info.pkts,
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002658 status->info_obsolete.time,
2659 status->info_obsolete.size,
2660 status->info_obsolete.pkts);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002661
2662 if (ctx->record.event_fn)
2663 return ctx->record.event_fn(evt, status, ctx->record.event_userdata);
2664 return 0;
2665}
2666
Zhiqiang Han620b9252021-11-09 14:23:20 +08002667static int wrapper_saveRecordStatistics(const char *location, DVR_WrapperRecordStatus_t *p_status)
2668{
2669 FILE *fp;
2670 char fpath[DVR_MAX_LOCATION_SIZE];
2671
2672 DVR_RETURN_IF_FALSE(location);
2673 DVR_RETURN_IF_FALSE(p_status);
2674
2675 sprintf(fpath, "%s.stats", location);
2676
2677 /*stats file*/
2678 if ((fp = fopen(fpath, "w"))) {
2679 char buf[256];
2680 snprintf(buf, sizeof(buf), ":%llu:%lu:%u\n",
2681 p_status->info.size - p_status->info_obsolete.size,
2682 p_status->info.time - p_status->info_obsolete.time,
2683 p_status->info.pkts - p_status->info_obsolete.pkts);
2684 fputs(buf, fp);
Zhiqiang Handc3bfe52022-07-07 10:48:39 +08002685 fflush(fp);
2686 fsync(fileno(fp));
Zhiqiang Han620b9252021-11-09 14:23:20 +08002687 fclose(fp);
2688 return DVR_SUCCESS;
2689 }
2690
2691 return DVR_FAILURE;
2692}
2693
2694
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002695static inline int record_startNextSegment(DVR_WrapperCtx_t *ctx)
2696{
2697 DVR_RecordStartParams_t param;
2698 DVR_RecordSegmentInfo_t seg_info;
2699 int i;
2700 int error;
2701
2702 memcpy(&param, &ctx->record.param_update, sizeof(param));
2703 memset(&ctx->record.param_update.segment, 0, sizeof(ctx->record.param_update.segment));
2704 ctx->record.param_update.segment.segment_id = ctx->record.next_segment_id++;
2705 for (i = 0; i < param.segment.nb_pids; i++) {
2706 if (param.segment.pid_action[i] != DVR_RECORD_PID_CLOSE) {
2707 ctx->record.param_update.segment.pids[ctx->record.param_update.segment.nb_pids] = param.segment.pids[i];
2708 ctx->record.param_update.segment.pid_action[ctx->record.param_update.segment.nb_pids] = DVR_RECORD_PID_KEEP;
2709 ctx->record.param_update.segment.nb_pids++;
2710 }
2711 }
2712 error = dvr_record_next_segment(ctx->record.recorder, &ctx->record.param_update, &seg_info);
2713 {
2714 DVR_RecordSegmentInfo_t new_seg_info =
2715 { .id = ctx->record.param_update.segment.segment_id, };
2716 wrapper_updateRecordSegment(ctx, &seg_info, U_ALL);
2717 wrapper_addRecordSegment(ctx, &new_seg_info);
2718 }
2719
Wentao MA96f68962022-06-15 19:45:35 +08002720 DVR_WRAPPER_INFO("record next segment(%llu)=(%d)\n", ctx->record.param_update.segment.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002721 return error;
2722}
2723
Wentao MA270dc0f2022-08-23 13:17:26 +08002724static inline int record_removeSegment(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordSegmentInfo_t *p_seg)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002725{
Wentao MA270dc0f2022-08-23 13:17:26 +08002726 return wrapper_removeRecordSegment(ctx, p_seg);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002727}
2728
2729/*should run periodically to update the current status*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002730static int process_generateRecordStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordStatus_t *status)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002731{
2732 /*the current seg is not covered in the statistics*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002733 DVR_WrapperRecordSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002734
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002735 /*re-calculate the all segments*/
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002736 memset(&ctx->record.status, 0, sizeof(ctx->record.status));
2737
2738 ctx->record.status.state = ctx->record.seg_status.state;
2739 ctx->record.status.pids.nb_pids = ctx->record.seg_status.info.nb_pids;
2740 memcpy(ctx->record.status.pids.pids,
2741 ctx->record.seg_status.info.pids,
2742 sizeof(ctx->record.status.pids.pids));
2743 ctx->current_segment_id = ctx->record.seg_status.info.id;
2744
Wentao MA270dc0f2022-08-23 13:17:26 +08002745 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
2746 if (p_seg->info.id != ctx->record.seg_status.info.id) {
2747 ctx->record.status.info.time += p_seg->info.duration;
2748 ctx->record.status.info.size += p_seg->info.size;
2749 ctx->record.status.info.pkts += p_seg->info.nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002750 }
2751 }
2752
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002753 ctx->record.status.info_obsolete = ctx->record.obsolete;
2754
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002755 wrapper_updateRecordSegment(ctx, &ctx->record.seg_status.info, U_ALL);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002756
2757 if (status) {
2758 *status = ctx->record.status;
2759 status->info.time += ctx->record.seg_status.info.duration;
2760 status->info.size += ctx->record.seg_status.info.size;
2761 status->info.pkts += ctx->record.seg_status.info.nb_packets;
2762 }
2763
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002764 return DVR_SUCCESS;
2765}
2766
2767
2768static int process_handleRecordEvent(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
2769{
2770 DVR_WrapperRecordStatus_t status;
2771
2772 memset(&status, 0, sizeof(status));
2773
Wentao MA96f68962022-06-15 19:45:35 +08002774 DVR_WRAPPER_INFO("evt (sn:%ld) 0x%x (state:%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002775 evt->sn, evt->record.event, evt->record.status.state);
hualing chend3b55ab2021-05-06 09:56:27 +08002776 if (ctx->record.param_update.segment.segment_id != evt->record.status.info.id) {
Wentao MA96f68962022-06-15 19:45:35 +08002777 DVR_WRAPPER_INFO("evt (sn:%ld) cur id:0x%x (event id:%d)\n",
Gong Ke2a0ebbe2021-05-25 15:22:50 +08002778 evt->sn, (int)ctx->record.param_update.segment.segment_id, (int)evt->record.status.info.id);
hualing chend3b55ab2021-05-06 09:56:27 +08002779 return 0;
2780 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002781 switch (evt->record.event)
2782 {
2783 case DVR_RECORD_EVENT_STATUS:
2784 {
2785 switch (evt->record.status.state)
2786 {
2787 case DVR_RECORD_STATE_OPENED:
2788 case DVR_RECORD_STATE_CLOSED:
2789 {
2790 ctx->record.seg_status = evt->record.status;
2791
2792 status.state = evt->record.status.state;
2793 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002794 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002795 } break;
2796 case DVR_RECORD_STATE_STARTED:
2797 {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002798 ctx->record.seg_status = evt->record.status;
2799
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002800 process_generateRecordStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002801 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002802 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002803
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002804 /*restart to next segment*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002805 if (ctx->record.param_open.segment_size
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002806 && evt->record.status.info.size >= ctx->record.param_open.segment_size) {
Wentao MA96f68962022-06-15 19:45:35 +08002807 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 +08002808 ctx->sn,
2809 evt->record.status.info.size,
2810 ctx->record.param_open.segment_size);
Zhiqiang Hand977e972020-05-11 11:30:47 +08002811 if (record_startNextSegment(ctx) != DVR_SUCCESS) {
2812 /*should notify the recording's stop*/
2813 int error = dvr_record_close(ctx->record.recorder);
Wentao MA96f68962022-06-15 19:45:35 +08002814 DVR_WRAPPER_INFO("stop record(%lu)=%d, failed to start new segment for recording.",
Zhiqiang Hand977e972020-05-11 11:30:47 +08002815 ctx->sn, error);
2816 status.state = DVR_RECORD_STATE_CLOSED;
2817 process_notifyRecord(ctx, DVR_RECORD_EVENT_WRITE_ERROR, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002818 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Hand977e972020-05-11 11:30:47 +08002819 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002820 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002821
2822 if (ctx->record.param_open.is_timeshift
2823 && ctx->record.param_open.max_time
2824 && status.info.time >= ctx->record.param_open.max_time) {
Wentao MA270dc0f2022-08-23 13:17:26 +08002825 DVR_WrapperRecordSegmentInfo_t *p_seg;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002826
2827 /*as the player do not support null playlist,
2828 there must be one segment existed at any time,
2829 we have to keep two segments before remove one*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002830 p_seg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
2831 if (p_seg == list_first_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head)) {
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002832 /*only one segment, waiting for more*/
Wentao MA96f68962022-06-15 19:45:35 +08002833 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 +08002834 status.info.size,
2835 ctx->record.param_open.max_time,
2836 ctx->record.param_open.segment_size);
2837 } else {
2838 /*timeshifting, remove the 1st segment and notify the player*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002839 record_removeSegment(ctx, p_seg);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002840
2841 process_generateRecordStatus(ctx, &status);
2842 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002843 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002844 }
2845 }
2846
Wentao MAf4072032022-06-30 13:50:45 +08002847 const loff_t actual_size = status.info.size;
2848 const loff_t max_size = ctx->record.param_open.max_size;
2849 const loff_t segment_size = ctx->record.param_open.segment_size;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002850
Wentao MAf4072032022-06-30 13:50:45 +08002851 if (ctx->record.param_open.is_timeshift && max_size) {
2852 if (actual_size >= max_size) {
Wentao MA270dc0f2022-08-23 13:17:26 +08002853 DVR_WrapperRecordSegmentInfo_t *p_seg;
Wentao MAf4072032022-06-30 13:50:45 +08002854 /*as the player do not support null playlist,
2855 there must be one segment existed at any time,
2856 we have to keep two segments before remove one*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002857 p_seg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
2858 if (p_seg == list_first_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head)) {
Wentao MAf4072032022-06-30 13:50:45 +08002859 /*only one segment, waiting for more*/
2860 DVR_WRAPPER_INFO("warning: the size(%lld) of record < max size of segment(%lld)\n",
2861 actual_size, segment_size);
2862 } else {
Wentao MA270dc0f2022-08-23 13:17:26 +08002863 record_removeSegment(ctx, p_seg);
Wentao MAf4072032022-06-30 13:50:45 +08002864
2865 process_generateRecordStatus(ctx, &status);
2866 process_notifyRecord(ctx, evt->record.event, &status);
2867 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
2868 }
2869 if (actual_size >= max_size + segment_size/2) {
2870 dvr_record_discard_coming_data(ctx->record.recorder,DVR_TRUE);
2871 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002872 } else {
Wentao MAf4072032022-06-30 13:50:45 +08002873 dvr_record_discard_coming_data(ctx->record.recorder,DVR_FALSE);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002874 }
2875 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002876 } break;
2877 case DVR_RECORD_STATE_STOPPED:
2878 {
2879 ctx->record.seg_status = evt->record.status;
2880
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002881 process_generateRecordStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002882 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002883 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002884 } break;
2885 default:
2886 break;
2887 }
2888 } break;
hualing chen4b7c15d2020-04-07 16:13:48 +08002889 case DVR_RECORD_EVENT_WRITE_ERROR: {
2890 ctx->record.seg_status = evt->record.status;
2891 status.state = evt->record.status.state;
2892 process_notifyRecord(ctx, evt->record.event, &status);
2893 }break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002894 default:
2895 break;
2896 }
2897 return DVR_SUCCESS;
2898}
2899
2900static inline int process_notifyPlayback(DVR_WrapperCtx_t *ctx, DVR_PlaybackEvent_t evt, DVR_WrapperPlaybackStatus_t *status)
2901{
Wentao MA270dc0f2022-08-23 13:17:26 +08002902 DVR_WRAPPER_INFO("notify(sn:%ld) evt(0x%x) statistics:state/cur/full/obsolete(%d/%ld/%ld/%ld)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002903 ctx->sn,
2904 evt,
2905 status->state,
2906 status->info_cur.time,
2907 status->info_full.time,
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002908 status->info_obsolete.time);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002909
2910 if (ctx->playback.event_fn)
2911 return ctx->playback.event_fn(evt, status, ctx->playback.event_userdata);
2912 return 0;
2913}
2914
2915/*should run periodically to update the current status*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002916static int process_generatePlaybackStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperPlaybackStatus_t *status)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002917{
2918 /*the current seg is not covered in the statistics*/
Wentao MA270dc0f2022-08-23 13:17:26 +08002919 DVR_WrapperPlaybackSegmentInfo_t *p_seg;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002920
2921 memset(&ctx->playback.status, 0, sizeof(ctx->playback.status));
2922 ctx->playback.status.pids = ctx->playback.pids_req;
2923
2924 ctx->playback.status.state = ctx->playback.seg_status.state;
2925 ctx->playback.status.speed = ctx->playback.seg_status.speed;
2926 ctx->playback.status.flags = ctx->playback.seg_status.flags;
2927 ctx->current_segment_id = ctx->playback.seg_status.segment_id;
2928
Wentao MA270dc0f2022-08-23 13:17:26 +08002929 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
2930 if (p_seg->seg_info.id == ctx->playback.seg_status.segment_id) {
2931 DVR_WRAPPER_INFO("calculate cur time :[%lld]time[%d]\n", p_seg->seg_info.id, p_seg->seg_info.duration);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002932 break;
hualing chen451c8f72022-03-09 13:05:52 +08002933 }
2934
Wentao MA270dc0f2022-08-23 13:17:26 +08002935 ctx->playback.status.info_cur.time += p_seg->seg_info.duration;
2936 ctx->playback.status.info_cur.size += p_seg->seg_info.size;
2937 ctx->playback.status.info_cur.pkts += p_seg->seg_info.nb_packets;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002938 }
Wentao MA270dc0f2022-08-23 13:17:26 +08002939 list_for_each_entry_reverse(p_seg, &ctx->segments, head) {
2940 ctx->playback.status.info_full.time += p_seg->seg_info.duration;
2941 ctx->playback.status.info_full.size += p_seg->seg_info.size;
2942 ctx->playback.status.info_full.pkts += p_seg->seg_info.nb_packets;
2943 DVR_WRAPPER_INFO("calculate full time :[%lld]time[%d]\n", p_seg->seg_info.id, p_seg->seg_info.duration);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002944 }
2945
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002946 if (status) {
2947 *status = ctx->playback.status;
2948 /*deal with current, lack size and pkts with the current*/
2949 status->info_cur.time += ctx->playback.seg_status.time_cur;
hualing chen56c0a162022-01-27 17:01:50 +08002950 //get last segment id
Wentao MA270dc0f2022-08-23 13:17:26 +08002951 DVR_WrapperRecordSegmentInfo_t *p_seg;
hualing chen56c0a162022-01-27 17:01:50 +08002952
Wentao MA270dc0f2022-08-23 13:17:26 +08002953 p_seg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
2954 if (ctx->playback.tf_full == DVR_TRUE && p_seg->info.id == ctx->current_segment_id) {
hualing chen56c0a162022-01-27 17:01:50 +08002955 status->disguised_info_obsolete.time = ctx->playback.obsolete.time + ctx->playback.seg_status.time_cur;
2956 status->info_obsolete.time = ctx->playback.obsolete.time;
Wentao MA270dc0f2022-08-23 13:17:26 +08002957 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 +08002958 }
2959 else
2960 {
Wentao MA270dc0f2022-08-23 13:17:26 +08002961 DVR_WRAPPER_INFO("warning not change start time :ctx->playback.tf_full[%d]id[%lld] [%lld] cur[%d]\n",ctx->playback.tf_full , p_seg->info.id, ctx->current_segment_id, status->info_cur.time);
hualing chen56c0a162022-01-27 17:01:50 +08002962 status->info_obsolete.time = ctx->playback.obsolete.time;
2963 status->disguised_info_obsolete.time = ctx->playback.obsolete.time;
2964 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002965 }
2966
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002967 return DVR_SUCCESS;
2968}
2969
2970static int process_handlePlaybackEvent(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
2971{
Wentao MA96f68962022-06-15 19:45:35 +08002972 DVR_WRAPPER_INFO("evt (sn:%ld) 0x%x (state:%d) cur(%lld:%u/%u)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002973 evt->sn, evt->playback.event,
2974 evt->playback.status.play_status.state,
2975 evt->playback.status.play_status.segment_id,
2976 evt->playback.status.play_status.time_cur,
2977 evt->playback.status.play_status.time_end);
2978
2979 /*evt PLAYTIME will break the last logic, do not save*/
hualing chene3797f02021-01-13 14:53:28 +08002980 if (evt->playback.event != DVR_PLAYBACK_EVENT_NOTIFY_PLAYTIME
2981 && evt->playback.event != DVR_PLAYBACK_EVENT_NODATA
2982 && evt->playback.event != DVR_PLAYBACK_EVENT_DATARESUME
2983 )
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002984 ctx->playback.last_event = evt->playback.event;
2985
2986 switch (evt->playback.event)
2987 {
2988 case DVR_PLAYBACK_EVENT_FIRST_FRAME:
2989 case DVR_PLAYBACK_EVENT_REACHED_END:
2990 case DVR_PLAYBACK_EVENT_TRANSITION_OK:
2991 case DVR_PLAYBACK_EVENT_NOTIFY_PLAYTIME:
hualing chenb5cd42e2020-04-15 17:03:34 +08002992 case DVR_PLAYBACK_EVENT_ERROR:
hualing chenf291cf32020-06-18 10:50:30 +08002993 case DVR_PLAYBACK_EVENT_REACHED_BEGIN:
hualing chene3797f02021-01-13 14:53:28 +08002994 case DVR_PLAYBACK_EVENT_NODATA:
2995 case DVR_PLAYBACK_EVENT_DATARESUME:
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002996 {
2997 DVR_WrapperPlaybackStatus_t status;
2998
2999 /*copy status of segment*/
3000 ctx->playback.seg_status = evt->playback.status.play_status;
3001
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08003002 /*generate status of the whole playback*/
3003 process_generatePlaybackStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003004
3005 if (evt->playback.event == DVR_PLAYBACK_EVENT_REACHED_END) {
Wentao MA96f68962022-06-15 19:45:35 +08003006 DVR_WRAPPER_INFO("playback(sn:%ld) event:0x%x\n", evt->sn, evt->playback.event);
hualing chenb9b358a2021-08-17 15:06:36 +08003007 if (ctx->playback.param_open.is_timeshift
3008 || ctx_isPlay_recording(ctx->playback.param_open.location)) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003009 /*wait for more data in recording*/
Zhiqiang Han31846002021-11-04 10:49:06 +08003010 }
3011 /*trust the low level, make NO check.
3012 As this evt is changed to only once due to some operations(paused) in low level.
3013 else if ((status.info_cur.time + DVR_PLAYBACK_END_GAP) >= ctx->playback.status.info_full.time) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003014 process_notifyPlayback(ctx, evt->playback.event, &status);
Zhiqiang Han31846002021-11-04 10:49:06 +08003015 }
3016 */
3017 else {
3018 process_notifyPlayback(ctx, evt->playback.event, &status);
hualing chenb5cd42e2020-04-15 17:03:34 +08003019 ctx->playback.reach_end = DVR_TRUE;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003020 }
hualing chenf291cf32020-06-18 10:50:30 +08003021 } else if (evt->playback.event != DVR_PLAYBACK_EVENT_REACHED_BEGIN) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003022 process_notifyPlayback(ctx, evt->playback.event, &status);
3023 }
3024 } break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003025 case DVR_PLAYBACK_EVENT_TRANSITION_FAILED:
3026 case DVR_PLAYBACK_EVENT_KEY_FAILURE:
3027 case DVR_PLAYBACK_EVENT_NO_KEY:
3028 {
Wentao MA96f68962022-06-15 19:45:35 +08003029 DVR_WRAPPER_INFO("playback(sn:%ld) error event:0x%x\n", evt->sn, evt->playback.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003030 } break;
3031 default:
3032 {
Wentao MA96f68962022-06-15 19:45:35 +08003033 DVR_WRAPPER_INFO("playback(sn:%ld) unknown event:0x%x\n", evt->sn, evt->playback.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08003034 } break;
3035 }
3036 return 0;
3037}
3038
3039static inline int process_handleEvents(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
3040{
3041 return (evt->type == W_REC)? process_handleRecordEvent(evt, ctx) : process_handlePlaybackEvent(evt, ctx);
3042}
3043
Wentao MA96f68962022-06-15 19:45:35 +08003044int dvr_wrapper_set_log_level (int level)
3045{
3046 if (level<LOG_LV_DEFAULT || level>LOG_LV_FATAL) {
3047 DVR_WRAPPER_ERROR("Invalid dvr log level:%d", g_dvr_log_level);
3048 return DVR_FAILURE;
3049 }
3050 g_dvr_log_level = level;
3051 DVR_WRAPPER_INFO("New dvr log level:%d", g_dvr_log_level);
3052 return DVR_SUCCESS;
3053}
3054
Wentao MA5629ad82022-08-24 10:03:02 +08003055int dvr_wrapper_set_ac4_preselection_id(DVR_WrapperPlayback_t playback, int presel_id)
3056{
3057 DVR_WrapperCtx_t *ctx;
3058 int error;
3059
3060 DVR_RETURN_IF_FALSE(playback==NULL);
3061
3062 ctx = ctx_getPlayback((unsigned long)playback);
3063 DVR_RETURN_IF_FALSE(ctx);
3064
3065 wrapper_mutex_lock(&ctx->wrapper_lock);
3066
3067 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
3068
3069 DVR_WRAPPER_INFO("set ac4 preselection id: %d", presel_id);
3070 error = dvr_playback_set_ac4_preselection_id(ctx->playback.player, presel_id);
3071
3072 wrapper_mutex_unlock(&ctx->wrapper_lock);
3073
3074 return error;
3075}
3076