blob: 92fcdd7fb81abf29e0fb4b7d39e4c99e6e971fdd [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
60 if (!lock->inited)
61 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{
322 DVR_WrapperEventCtx_t *pevt;
323
324 pthread_mutex_lock(list_lock);
325 if (list_empty(list))
326 pevt = NULL;
327 else {
328 pevt = list_first_entry(list, DVR_WrapperEventCtx_t, head);
329 list_del(&pevt->head);
330 }
331 pthread_mutex_unlock(list_lock);
332
333 return pevt;
334}
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{
369 DVR_WrapperEventCtx_t *pevt, *pevt_tmp;
370 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);
384 list_for_each_entry_safe(pevt, pevt_tmp, evt_list, head) {
385 for (i = 0; i < cnt; i++) {
386 if (pevt->sn == sns[i]) {
387 found = 1;
388 break;
389 }
390 }
391 if (!found) {
392 list_del(&pevt->head);
393 ctx_freeEvent(pevt);
394 }
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 MA96f68962022-06-15 19:45:35 +0800425 DVR_WRAPPER_INFO(" not found play is recing [%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) {
485 pthread_condattr_t attr;
486 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{
595 DVR_WrapperThreadCtx_t *tctx = (DVR_WrapperThreadCtx_t *)arg;
596 DVR_WrapperEventCtx_t *evt;
597
598 pthread_mutex_lock(&tctx->lock);
599
600 while (tctx->running) {
601 {
602 int ret;
hualing chene3797f02021-01-13 14:53:28 +0800603
Zhiqiang Han18f42c82021-08-11 17:13:28 +0800604 evt = (tctx->type == W_REC)? ctx_getRecordEvent() : ctx_getPlaybackEvent();
605 if (!evt)
606 ret = wrapper_threadWait(tctx);
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 MA96f68962022-06-15 19:45:35 +0800616 DVR_WRAPPER_INFO("start name(%s) sn(%d) running(%d) type(%d)\n", tctx->name, (int)ctx->sn, tctx->running, tctx->type);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800617 if (tctx->running) {
618 /*
619 continue not break,
620 make all events consumed, or mem leak
621 */
Gong Kefdb31922022-06-17 17:11:16 +0800622 if (!wrapper_mutex_lock_if(&ctx->wrapper_lock, &tctx->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) {
628 pthread_mutex_unlock(&tctx->lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800629 process_handleEvents(evt, ctx);
Zhiqiang Han3b9c9082021-11-10 10:41:09 +0800630 pthread_mutex_lock(&tctx->lock);
631 }
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
639 evt = (tctx->type == W_REC)? ctx_getRecordEvent() : ctx_getPlaybackEvent();
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800640 }
Wentao MA96f68962022-06-15 19:45:35 +0800641 DVR_WRAPPER_INFO("start name(%s) running(%d) type(%d) con...\n", tctx->name, tctx->running, tctx->type);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800642 }
643
644 pthread_mutex_unlock(&tctx->lock);
Wentao MA96f68962022-06-15 19:45:35 +0800645 DVR_WRAPPER_INFO("end name(%s) running(%d) type(%d) end...\n", tctx->name, tctx->running, tctx->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{
669 DVR_WrapperPlaybackSegmentInfo_t *pseg, *pseg_tmp;
670 list_for_each_entry_safe(pseg, pseg_tmp, &ctx->segments, head) {
671 list_del(&pseg->head);
672 free(pseg);
673 }
674}
675
676static inline void _updatePlaybackSegment(DVR_WrapperPlaybackSegmentInfo_t *pseg,
677 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))
681 pseg->seg_info = *seg_info;
682 else if (update_flags & U_PIDS) {
683 pseg->seg_info.nb_pids = seg_info->nb_pids;
684 memcpy(pseg->seg_info.pids, seg_info->pids, sizeof(pseg->seg_info.pids));
685 } else if (update_flags & U_STAT) {
686 pseg->seg_info.duration = seg_info->duration;
687 pseg->seg_info.size = seg_info->size;
688 pseg->seg_info.nb_packets = seg_info->nb_packets;
689 }
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))
hualing chen03fd4942021-07-15 15:56:41 +0800693 dvr_playback_update_duration(ctx->playback.player,pseg->seg_info.id,pseg->seg_info.duration);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800694 /*no changes
695 DVR_PlaybackSegmentFlag_t flags;
696 pseg->playback_info.segment_id = pseg->seg_info.id;
697 strncpy(pseg->playback_info.location,
698 ctx->playback.param_open.location, sizeof(pseg->playback_info.location));
699 pseg->playback_info.pids = ctx->playback.pids_req;
700 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;
703 pseg->playback_info.flags = flags;
704 */
705}
706
707static int wrapper_updatePlaybackSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info, int update_flags)
708{
709 DVR_WrapperPlaybackSegmentInfo_t *pseg;
710
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*/
720 pseg =
721 list_first_entry(&ctx->segments, DVR_WrapperPlaybackSegmentInfo_t, head);
722 if (pseg->seg_info.id == seg_info->id) {
723 _updatePlaybackSegment(pseg, seg_info, update_flags, ctx);
724 } else {
725 list_for_each_entry_reverse(pseg, &ctx->segments, head) {
726 if (pseg->seg_info.id == seg_info->id) {
727 _updatePlaybackSegment(pseg, seg_info, update_flags, ctx);
728 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
764static void _updateRecordSegment(DVR_WrapperRecordSegmentInfo_t *pseg,
765 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))
769 pseg->info = *seg_info;
770 else if (update_flags & U_PIDS) {
771 pseg->info.nb_pids = seg_info->nb_pids;
772 memcpy(pseg->info.pids, seg_info->pids, sizeof(pseg->info.pids));
773 } else if (update_flags & U_STAT) {
774 pseg->info.duration = seg_info->duration;
775 pseg->info.size = seg_info->size;
776 pseg->info.nb_packets = seg_info->nb_packets;
777 }
778}
779
780static int wrapper_updateRecordSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info, int update_flags)
781{
hualing chen266b9502020-04-04 17:39:39 +0800782 DVR_WrapperRecordSegmentInfo_t *pseg = 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)) {
786 pseg =
787 list_first_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
788 if (pseg->info.id == seg_info->id) {
789 _updateRecordSegment(pseg, seg_info, update_flags, ctx);
790 } else {
791 list_for_each_entry_reverse(pseg, &ctx->segments, head) {
792 if (pseg->info.id == seg_info->id) {
793 _updateRecordSegment(pseg, seg_info, update_flags, ctx);
794 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{
837 DVR_WrapperPlaybackSegmentInfo_t *pseg;
838 int error;
839
840 error = 0;
841 pseg = (DVR_WrapperPlaybackSegmentInfo_t *)calloc(1, sizeof(DVR_WrapperPlaybackSegmentInfo_t));
842 if (!pseg) {
843 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
848 /*copy the orignal segment info*/
849 pseg->seg_info = *seg_info;
850 /*generate the segment info used in playback*/
851 pseg->playback_info.segment_id = pseg->seg_info.id;
852 strncpy(pseg->playback_info.location, ctx->playback.param_open.location, sizeof(pseg->playback_info.location));
853 pseg->playback_info.pids = *p_pids;
854 pseg->playback_info.flags = flags;
855 list_add(&pseg->head, &ctx->segments);
Wentao MA96f68962022-06-15 19:45:35 +0800856 DVR_WRAPPER_INFO("start to add segment %lld\n", pseg->playback_info.segment_id);
hualing chen03fd4942021-07-15 15:56:41 +0800857 pseg->playback_info.duration = pseg->seg_info.duration;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800858
859 error = dvr_playback_add_segment(ctx->playback.player, &pseg->playback_info);
860 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +0800861 DVR_WRAPPER_INFO("fail to add segment %lld (%d)\n", pseg->playback_info.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800862 } else {
863 ctx->playback.status.info_full.time += pseg->seg_info.duration;
864 ctx->playback.status.info_full.size += pseg->seg_info.size;
865 ctx->playback.status.info_full.pkts += pseg->seg_info.nb_packets;
866 }
867
868 return error;
869}
870
871static int wrapper_addRecordSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info)
872{
873 DVR_WrapperRecordSegmentInfo_t *pseg;
874 int error;
hualing chenab0d1262021-09-26 15:22:50 +0800875 int sn = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800876
877 error = 0;
878 pseg = (DVR_WrapperRecordSegmentInfo_t *)calloc(1, sizeof(DVR_WrapperRecordSegmentInfo_t));
879 if (!pseg) {
880 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +0800881 DVR_WRAPPER_INFO("memory fail\n");
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800882 }
883 pseg->info = *seg_info;
884 list_add(&pseg->head, &ctx->segments);
hualing chenab0d1262021-09-26 15:22:50 +0800885
hualing chenb9b358a2021-08-17 15:06:36 +0800886 if (ctx->record.param_open.is_timeshift ||
887 (sn = ctx_isRecord_playing(ctx->record.param_open.location))) {
888
889 DVR_WrapperCtx_t *ctx_playback;
890 if (ctx->record.param_open.is_timeshift)
891 ctx_playback = ctx_getPlayback(sn_timeshift_playback);
892 else
893 ctx_playback = ctx_getPlayback(sn);
894
Wentao MA96f68962022-06-15 19:45:35 +0800895 DVR_WRAPPER_INFO("ctx_playback ---- add segment\n");
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800896
897 if (ctx_playback) {
Gong Kefdb31922022-06-17 17:11:16 +0800898 wrapper_mutex_lock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800899 if (ctx_valid(ctx_playback)) {
900 DVR_PlaybackSegmentFlag_t flags;
901
902 /*only if playback has started, the previous segments have been loaded*/
903 if (!list_empty(&ctx_playback->segments)) {
904 flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
Gong Ke2a0ebbe2021-05-25 15:22:50 +0800905 if (ctx->record.param_open.flags & DVR_RECORD_FLAG_SCRAMBLED)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800906 flags |= DVR_PLAYBACK_SEGMENT_ENCRYPTED;
907 wrapper_addPlaybackSegment(ctx_playback, seg_info, &ctx_playback->playback.pids_req, flags);
hualing chen451c8f72022-03-09 13:05:52 +0800908 } else {
Wentao MA96f68962022-06-15 19:45:35 +0800909 DVR_WRAPPER_INFO("ctx_playback list_empty(&ctx_playback->segments) true\n");
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800910 }
hualing chenb9b358a2021-08-17 15:06:36 +0800911 } else {
Wentao MA96f68962022-06-15 19:45:35 +0800912 DVR_WRAPPER_INFO("ctx_playback ---- not valid\n");
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800913 }
Gong Kefdb31922022-06-17 17:11:16 +0800914 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800915 }
hualing chen451c8f72022-03-09 13:05:52 +0800916 else
917 {
Wentao MA96f68962022-06-15 19:45:35 +0800918 DVR_WRAPPER_INFO("ctx_playback ---- not valid 1\n");
hualing chen451c8f72022-03-09 13:05:52 +0800919 }
Zhiqiang Hane0a1c382021-06-08 11:28:05 +0800920 } else {
Wentao MA96f68962022-06-15 19:45:35 +0800921 DVR_WRAPPER_INFO("ctx_playback -sn[%d]-\n", sn);
Zhiqiang Hane0a1c382021-06-08 11:28:05 +0800922 dvr_segment_link_op(ctx->record.param_open.location, 1, &seg_info->id, LSEG_OP_ADD);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800923 }
924
925 return error;
926}
927
928static int wrapper_removePlaybackSegment(DVR_WrapperCtx_t *ctx, DVR_RecordSegmentInfo_t *seg_info)
929{
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800930 int error = -1;
931 DVR_WrapperPlaybackSegmentInfo_t *pseg = NULL, *pseg_tmp;
hualing chenb9a1a2c2021-12-31 11:27:59 +0800932 uint32_t off_set = 0;
Wentao MA96f68962022-06-15 19:45:35 +0800933 DVR_WRAPPER_INFO("timeshift, remove playback(sn:%ld) segment(%lld) ...\n", ctx->sn, seg_info->id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800934
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800935 list_for_each_entry_safe_reverse(pseg, pseg_tmp, &ctx->segments, head) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800936 if (pseg->seg_info.id == seg_info->id) {
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800937
938 if (ctx->current_segment_id == seg_info->id) {
939 DVR_WrapperPlaybackSegmentInfo_t *next_seg;
940
941 /*drive the player out of this will-be-deleted segment*/
942 next_seg = list_prev_entry(pseg, head);
943
944 if (ctx->playback.speed != 100.0f) {
945 error = dvr_playback_resume(ctx->playback.player);
Wentao MA96f68962022-06-15 19:45:35 +0800946 DVR_WRAPPER_INFO("timeshift, playback(sn:%ld), resume for new start (%d)\n", ctx->sn, error);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800947 }
hualing chenb9a1a2c2021-12-31 11:27:59 +0800948 if (ctx->playback.param_open.vendor == DVR_PLAYBACK_VENDOR_AMAZON)
949 off_set = 10 * 1000;
950 error = dvr_playback_seek(ctx->playback.player, next_seg->seg_info.id, off_set);
Wentao MA96f68962022-06-15 19:45:35 +0800951 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 +0800952
953 if (ctx->playback.speed == 0.0f) {
954 error = dvr_playback_pause(ctx->playback.player, DVR_FALSE);
Wentao MA96f68962022-06-15 19:45:35 +0800955 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 +0800956 } else if (ctx->playback.speed != 100.0f) {
957 DVR_PlaybackSpeed_t dvr_speed = {
958 .speed = { ctx->playback.speed },
959 .mode = ( ctx->playback.speed > 0) ? DVR_PLAYBACK_FAST_FORWARD : DVR_PLAYBACK_FAST_BACKWARD
960 };
961 error = dvr_playback_set_speed(ctx->playback.player, dvr_speed);
Wentao MA96f68962022-06-15 19:45:35 +0800962 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 +0800963 }
964 }
965
966 error = dvr_playback_remove_segment(ctx->playback.player, seg_info->id);
967 if (error) {
968 /*remove playack segment fail*/
Wentao MA96f68962022-06-15 19:45:35 +0800969 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 +0800970 }
971
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800972 list_del(&pseg->head);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800973
974 /*record the obsolete*/
975 ctx->playback.obsolete.time += pseg->seg_info.duration;
976 ctx->playback.obsolete.size += pseg->seg_info.size;
977 ctx->playback.obsolete.pkts += pseg->seg_info.nb_packets;
Wentao MA96f68962022-06-15 19:45:35 +0800978 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 +0800979 dvr_playback_set_obsolete(ctx->playback.player, ctx->playback.obsolete.time);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800980 free(pseg);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800981 break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800982 }
983 }
984
Wentao MA96f68962022-06-15 19:45:35 +0800985 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 +0800986
987 return error;
988}
989
990static int wrapper_removeRecordSegment(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordSegmentInfo_t *seg_info)
991{
992 int error;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +0800993 DVR_WrapperRecordSegmentInfo_t *pseg, *pseg_tmp;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800994
Wentao MA96f68962022-06-15 19:45:35 +0800995 DVR_WRAPPER_INFO("---timeshift, remove record(sn:%ld) segment(%lld) ...\n", ctx->sn, seg_info->info.id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800996
997 /*if timeshifting, notify the playback first, then deal with record*/
998 if (ctx->record.param_open.is_timeshift) {
999 DVR_WrapperCtx_t *ctx_playback = ctx_getPlayback(sn_timeshift_playback);
1000
1001 if (ctx_playback) {
Gong Kefdb31922022-06-17 17:11:16 +08001002 wrapper_mutex_lock(&ctx_playback->wrapper_lock);
hualing chen56c0a162022-01-27 17:01:50 +08001003 if (ctx_playback->current_segment_id == seg_info->info.id && ctx_playback->playback.speed == 100.0f) {
1004 ctx_playback->playback.tf_full = DVR_TRUE;
Wentao MA96f68962022-06-15 19:45:35 +08001005 DVR_WRAPPER_INFO("timeshift, not remove record(sn:%ld) segment(%lld) .(%d) (%f).isplaying.\n", ctx->sn, seg_info->info.id, DVR_TRUE, ctx_playback->playback.speed);
Gong Kefdb31922022-06-17 17:11:16 +08001006 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
hualing chen56c0a162022-01-27 17:01:50 +08001007 return DVR_SUCCESS;
1008 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001009 DVR_WRAPPER_INFO("timeshift, start remove record(sn:%ld) segment(%lld) (%lld).(%f)..\n", ctx->sn, seg_info->info.id, ctx_playback->current_segment_id,ctx_playback->playback.speed);
hualing chen56c0a162022-01-27 17:01:50 +08001010 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001011 if (ctx_valid(ctx_playback)
1012 && ctx_playback->sn == sn_timeshift_playback
1013 && !list_empty(&ctx_playback->segments)) {
1014 error = wrapper_removePlaybackSegment(ctx_playback, &seg_info->info);
1015 }
hualing chen56c0a162022-01-27 17:01:50 +08001016 ctx_playback->playback.tf_full = DVR_FALSE;
Gong Kefdb31922022-06-17 17:11:16 +08001017 wrapper_mutex_unlock(&ctx_playback->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001018 }
1019 }
1020
Zhiqiang Hanbc3019b2022-03-21 11:31:21 +08001021 uint64_t id = seg_info->info.id;
1022
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001023 list_for_each_entry_safe_reverse(pseg, pseg_tmp, &ctx->segments, head) {
Zhiqiang Hanbc3019b2022-03-21 11:31:21 +08001024 if (pseg->info.id == id) {
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001025 list_del(&pseg->head);
1026
1027 /*record the obsolete*/
1028 ctx->record.obsolete.time += pseg->info.duration;
1029 ctx->record.obsolete.size += pseg->info.size;
1030 ctx->record.obsolete.pkts += pseg->info.nb_packets;
1031
1032 free(pseg);
1033 break;
1034 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001035 }
1036
Zhiqiang Hanbc3019b2022-03-21 11:31:21 +08001037 error = dvr_segment_delete(ctx->record.param_open.location, id);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001038
Wentao MA96f68962022-06-15 19:45:35 +08001039 DVR_WRAPPER_INFO("timeshift, remove record(sn:%ld) segment(%lld) =(%d)\n", ctx->sn, id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001040
1041 return error;
1042}
1043
1044int dvr_wrapper_open_record (DVR_WrapperRecord_t *rec, DVR_WrapperRecordOpenParams_t *params)
1045{
1046 int error;
1047 DVR_WrapperCtx_t *ctx;
1048 DVR_RecordOpenParams_t open_param;
1049
1050 DVR_RETURN_IF_FALSE(rec);
1051 DVR_RETURN_IF_FALSE(params);
1052
1053 /*get a free ctx*/
1054 ctx = ctx_getRecord(0);
1055 DVR_RETURN_IF_FALSE(ctx);
1056
Gong Kefdb31922022-06-17 17:11:16 +08001057 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001058
Wentao MA96f68962022-06-15 19:45:35 +08001059 DVR_WRAPPER_INFO("open record(dmx:%d) .istf(%d)..time (%ld)ms max size(%lld)byte seg size(%lld)byte\n",
hualing chen51652f02020-12-29 16:59:31 +08001060 params->dmx_dev_id, params->is_timeshift, params->max_time, params->max_size, params->segment_size);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001061
1062 ctx_reset(ctx);
1063
1064 ctx->record.param_open = *params;
1065 ctx->record.event_fn = params->event_fn;
1066 ctx->record.event_userdata = params->event_userdata;
1067 ctx->record.next_segment_id = 0;
1068 ctx->current_segment_id = 0;
1069 INIT_LIST_HEAD(&ctx->segments);
1070 ctx->sn = get_sn();
1071
1072 wrapper_requestThreadFor(ctx);
1073
hualing chen266b9502020-04-04 17:39:39 +08001074 memset(&open_param, 0, sizeof(DVR_RecordOpenParams_t));
Yahui Hance15e9c2020-12-08 18:08:32 +08001075 open_param.fend_dev_id = params->fend_dev_id;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001076 open_param.dmx_dev_id = params->dmx_dev_id;
1077 open_param.data_from_memory = 0;
1078 open_param.flags = params->flags;
Yahui Han15a00f12021-11-15 19:44:39 +08001079 if (params->flush_size) {
1080 open_param.notification_size = params->flush_size;
1081 } else {
1082 open_param.notification_size = 64*1024;
1083 }
hualing chen002e5b92022-02-23 17:51:21 +08001084 open_param.notification_time = 400;//ms
Zhiqiang Han31505452020-05-06 15:08:10 +08001085 open_param.flush_size = params->flush_size;
hualing chen03fd4942021-07-15 15:56:41 +08001086 open_param.ringbuf_size = params->ringbuf_size;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001087 open_param.event_fn = wrapper_record_event_handler;
1088 open_param.event_userdata = (void*)ctx->sn;
Yahui Han1fbf3292021-11-08 18:17:19 +08001089 if (params->keylen) {
1090 open_param.clearkey = params->clearkey;
1091 open_param.cleariv = params->cleariv;
1092 open_param.keylen = params->keylen;
1093 }
wentao.ma35a69d42022-03-10 18:08:40 +08001094 open_param.force_sysclock = params->force_sysclock;
Wentao MAeeffdb02022-06-27 16:34:35 +08001095 open_param.guarded_segment_size = params->segment_size/2*3;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001096
1097 error = dvr_record_open(&ctx->record.recorder, &open_param);
1098 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001099 DVR_WRAPPER_INFO("record(dmx:%d) open fail(error:%d).\n", params->dmx_dev_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001100 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001101 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001102 wrapper_releaseThreadForType(ctx->type);
1103 return DVR_FAILURE;
1104 }
1105 if (params->is_timeshift)
1106 sn_timeshift_record = ctx->sn;
1107
Wentao MA96f68962022-06-15 19:45:35 +08001108 DVR_WRAPPER_INFO("record(dmx:%d) openned ok(sn:%ld).\n", params->dmx_dev_id, ctx->sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001109
Yahui Han1fbf3292021-11-08 18:17:19 +08001110 if (params->crypto_fn) {
1111 error = dvr_record_set_encrypt_callback(ctx->record.recorder, params->crypto_fn, params->crypto_data);
1112 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001113 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 +08001114 }
hualing chen266b9502020-04-04 17:39:39 +08001115 }
1116
Gong Kefdb31922022-06-17 17:11:16 +08001117 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001118
1119 *rec = (DVR_WrapperRecord_t)ctx->sn;
1120 return DVR_SUCCESS;
1121}
1122
1123int dvr_wrapper_close_record (DVR_WrapperRecord_t rec)
1124{
1125 DVR_WrapperCtx_t *ctx;
1126 DVR_RecordSegmentInfo_t seg_info;
1127 int error;
1128
1129 DVR_RETURN_IF_FALSE(rec);
1130
1131 ctx = ctx_getRecord((unsigned long)rec);
1132 DVR_RETURN_IF_FALSE(ctx);
1133
Gong Kefdb31922022-06-17 17:11:16 +08001134 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001135 DVR_WRAPPER_INFO("close record(sn:%ld)\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001136 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001137
1138 memset(&seg_info, 0, sizeof(seg_info));
1139 error = dvr_record_stop_segment(ctx->record.recorder, &seg_info);
1140
1141 error = dvr_record_close(ctx->record.recorder);
1142
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001143 if (ctx->record.param_open.is_timeshift)
1144 sn_timeshift_record = 0;
1145
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001146 ctx_freeSegments(ctx);
1147
Wentao MA96f68962022-06-15 19:45:35 +08001148 DVR_WRAPPER_INFO("record(sn:%ld) closed = (%d).\n", ctx->sn, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001149 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001150 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001151
1152 wrapper_releaseThreadForType(ctx->type);
1153
1154 return error;
1155}
1156
1157int dvr_wrapper_start_record (DVR_WrapperRecord_t rec, DVR_WrapperRecordStartParams_t *params)
1158{
1159 DVR_WrapperCtx_t *ctx;
1160 DVR_RecordStartParams_t *start_param;
1161 int i;
1162 int error;
1163
1164 DVR_RETURN_IF_FALSE(rec);
1165 DVR_RETURN_IF_FALSE(params);
1166
1167 ctx = ctx_getRecord((unsigned long)rec);
1168 DVR_RETURN_IF_FALSE(ctx);
1169
Gong Kefdb31922022-06-17 17:11:16 +08001170 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001171 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 +08001172 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001173
1174 start_param = &ctx->record.param_start;
1175 memset(start_param, 0, sizeof(*start_param));
1176 strncpy(start_param->location, ctx->record.param_open.location, sizeof(start_param->location));
1177 start_param->segment.segment_id = ctx->record.next_segment_id++;
1178 start_param->segment.nb_pids = params->pids_info.nb_pids;
1179 for (i = 0; i < params->pids_info.nb_pids; i++) {
1180 start_param->segment.pids[i] = params->pids_info.pids[i];
1181 start_param->segment.pid_action[i] = DVR_RECORD_PID_CREATE;
1182 }
hualing chena5f03222021-12-02 11:22:35 +08001183 if (params->save_rec_file == 0)//default is not save
1184 dvr_segment_del_by_location(start_param->location);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001185 {
1186 /*sync to update for further use*/
1187 DVR_RecordStartParams_t *update_param;
1188 update_param = &ctx->record.param_update;
1189 memcpy(update_param, start_param, sizeof(*update_param));
1190 for (i = 0; i < update_param->segment.nb_pids; i++)
1191 update_param->segment.pid_action[i] = DVR_RECORD_PID_KEEP;
1192 }
1193
1194 error = dvr_record_start_segment(ctx->record.recorder, start_param);
1195 {
1196 DVR_RecordSegmentInfo_t new_seg_info =
1197 { .id = start_param->segment.segment_id, };
1198 wrapper_addRecordSegment(ctx, &new_seg_info);
1199 }
1200
Wentao MA96f68962022-06-15 19:45:35 +08001201 DVR_WRAPPER_INFO("record(sn:%ld) started = (%d)\n", ctx->sn, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001202
Gong Kefdb31922022-06-17 17:11:16 +08001203 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001204
1205 return error;
1206}
1207
1208int dvr_wrapper_stop_record (DVR_WrapperRecord_t rec)
1209{
1210 DVR_WrapperCtx_t *ctx;
1211 DVR_RecordSegmentInfo_t seg_info;
1212 int error;
1213
1214 DVR_RETURN_IF_FALSE(rec);
1215
1216 ctx = ctx_getRecord((unsigned long)rec);
1217 DVR_RETURN_IF_FALSE(ctx);
1218
Gong Kefdb31922022-06-17 17:11:16 +08001219 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001220 DVR_WRAPPER_INFO("stop record(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001221 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001222
1223 memset(&seg_info, 0, sizeof(seg_info));
1224 error = dvr_record_stop_segment(ctx->record.recorder, &seg_info);
1225 wrapper_updateRecordSegment(ctx, &seg_info, U_ALL);
1226
Wentao MA96f68962022-06-15 19:45:35 +08001227 DVR_WRAPPER_INFO("record(sn:%ld) stopped = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001228 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001229
1230 return error;
1231}
1232
hualing chen03fd4942021-07-15 15:56:41 +08001233int dvr_wrapper_pause_record (DVR_WrapperRecord_t rec)
1234{
1235 DVR_WrapperCtx_t *ctx;
1236 int error;
1237
1238 DVR_RETURN_IF_FALSE(rec);
1239
1240 ctx = ctx_getRecord((unsigned long)rec);
1241 DVR_RETURN_IF_FALSE(ctx);
1242
Gong Kefdb31922022-06-17 17:11:16 +08001243 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001244 DVR_WRAPPER_INFO("pause record(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001245 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001246
1247 error = dvr_record_pause(ctx->record.recorder);
1248
Wentao MA96f68962022-06-15 19:45:35 +08001249 DVR_WRAPPER_INFO("record(sn:%ld) pauseed = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001250 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001251
1252 return error;
1253}
1254
1255int dvr_wrapper_resume_record (DVR_WrapperRecord_t rec)
1256{
1257 DVR_WrapperCtx_t *ctx;
1258 int error;
1259
1260 DVR_RETURN_IF_FALSE(rec);
1261
1262 ctx = ctx_getRecord((unsigned long)rec);
1263 DVR_RETURN_IF_FALSE(ctx);
1264
Gong Kefdb31922022-06-17 17:11:16 +08001265 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001266 DVR_WRAPPER_INFO("resume record(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001267 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001268
1269 error = dvr_record_resume(ctx->record.recorder);
1270
Wentao MA96f68962022-06-15 19:45:35 +08001271 DVR_WRAPPER_INFO("record(sn:%ld) resumed = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001272 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001273
1274 return error;
1275}
1276
Wentao MAcdea4762022-04-26 13:28:56 +08001277/* Return true if arr1 contains all elements in arr2 */
1278static DVR_Bool_t pids_test_include( DVR_StreamPid_t* arr1, int size1,
1279 DVR_StreamPid_t* arr2, int size2)
wentao.maa69578c2022-04-07 09:27:39 +08001280{
Wentao MAcdea4762022-04-26 13:28:56 +08001281 DVR_Bool_t ret = DVR_TRUE;
1282 for (int i=0;i<size2;i++)
1283 { // iterate all elements in arr2 to check if they exist in arr1
1284 DVR_Bool_t found=DVR_FALSE;
1285 for (int j=0;j<size1;j++)
wentao.maa69578c2022-04-07 09:27:39 +08001286 {
Wentao MAcdea4762022-04-26 13:28:56 +08001287 if (arr2[i].pid == arr1[j].pid)
wentao.maa69578c2022-04-07 09:27:39 +08001288 {
1289 found=DVR_TRUE;
1290 break;
1291 }
1292 }
1293 if (found == DVR_FALSE)
1294 {
Wentao MAcdea4762022-04-26 13:28:56 +08001295 ret=DVR_FALSE;
wentao.maa69578c2022-04-07 09:27:39 +08001296 break;
1297 }
1298 }
Wentao MAcdea4762022-04-26 13:28:56 +08001299 return ret;
1300}
1301
1302static DVR_Bool_t pids_equal(const DVR_RecordSegmentStartParams_t* p1,
1303 const DVR_WrapperUpdatePidsParams_t* p2)
1304{
1305 int i=0;
1306 char buf[128]={0};
1307 int cnt=0;
1308 int chars=0;
1309
1310 DVR_RETURN_IF_FALSE(p1 != NULL && p2 != NULL);
1311 DVR_RETURN_IF_FALSE(p1->nb_pids>0 && p2->nb_pids>0);
1312
1313 DVR_Bool_t cond1 = pids_test_include(p1->pids,p1->nb_pids,p2->pids,p2->nb_pids);
1314 DVR_Bool_t cond2 = pids_test_include(p2->pids,p2->nb_pids,p1->pids,p1->nb_pids);
1315 DVR_Bool_t is_equal = (cond1 && cond2);
1316
1317 for (i=0;i<p1->nb_pids;i++)
1318 {
1319 chars = snprintf(buf+cnt,sizeof(buf)-cnt,"0x%hx,",p1->pids[i].pid);
1320 if (chars<0)
1321 {
1322 break;
1323 }
1324 cnt += chars;
1325 }
Wentao MA96f68962022-06-15 19:45:35 +08001326 DVR_INFO("%s nb_pids1:%d, pids1: %s",__func__,p1->nb_pids,buf);
Wentao MAcdea4762022-04-26 13:28:56 +08001327 memset(buf,0,sizeof(buf));
1328
1329 for (i=0,cnt=0;i<p2->nb_pids;i++)
1330 {
1331 chars = snprintf(buf+cnt,sizeof(buf)-cnt,"0x%hx,",p2->pids[i].pid);
1332 if (chars<0)
1333 {
1334 break;
1335 }
1336 cnt += chars;
1337 }
Wentao MA96f68962022-06-15 19:45:35 +08001338 DVR_INFO("%s nb_pids2:%d, pids2: %s",__func__,p2->nb_pids,buf);
1339 DVR_INFO("%s is_equal:%d",__func__,is_equal);
wentao.maa69578c2022-04-07 09:27:39 +08001340 return is_equal;
1341}
1342
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001343int dvr_wrapper_update_record_pids (DVR_WrapperRecord_t rec, DVR_WrapperUpdatePidsParams_t *params)
1344{
1345 DVR_WrapperCtx_t *ctx;
1346 DVR_RecordStartParams_t *start_param;
wentao.maa69578c2022-04-07 09:27:39 +08001347 DVR_RecordSegmentInfo_t seg_info;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001348 int i;
1349 int error;
1350
1351 DVR_RETURN_IF_FALSE(rec);
1352 DVR_RETURN_IF_FALSE(params);
1353
1354 ctx = ctx_getRecord((unsigned long)rec);
1355 DVR_RETURN_IF_FALSE(ctx);
1356
Gong Kefdb31922022-06-17 17:11:16 +08001357 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001358 DVR_WRAPPER_INFO("update record(sn:%ld)\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001359 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001360
1361 start_param = &ctx->record.param_update;
wentao.maa69578c2022-04-07 09:27:39 +08001362 if (pids_equal(&(start_param->segment),params))
1363 {
Gong Kefdb31922022-06-17 17:11:16 +08001364 wrapper_mutex_unlock(&ctx->wrapper_lock);
wentao.maa69578c2022-04-07 09:27:39 +08001365 return DVR_TRUE;
1366 }
1367
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001368 memset(start_param, 0, sizeof(*start_param));
1369 strncpy(start_param->location, ctx->record.param_open.location, sizeof(start_param->location));
1370 start_param->segment.segment_id = ctx->record.next_segment_id++;
1371 start_param->segment.nb_pids = params->nb_pids;
1372 for (i = 0; i < params->nb_pids; i++) {
1373 start_param->segment.pids[i] = params->pids[i];
1374 start_param->segment.pid_action[i] = params->pid_action[i];
1375 }
1376 error = dvr_record_next_segment(ctx->record.recorder, start_param, &seg_info);
1377 {
1378 DVR_RecordSegmentInfo_t new_seg_info =
1379 { .id = start_param->segment.segment_id, };
1380 wrapper_updateRecordSegment(ctx, &seg_info, U_PIDS);
1381 wrapper_addRecordSegment(ctx, &new_seg_info);
1382 }
1383
Wentao MA96f68962022-06-15 19:45:35 +08001384 DVR_WRAPPER_INFO("record(sn:%ld) updated = (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08001385 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001386
1387 return error;
1388}
1389
1390int dvr_wrapper_get_record_status(DVR_WrapperRecord_t rec, DVR_WrapperRecordStatus_t *status)
1391{
1392 DVR_WrapperCtx_t *ctx;
1393 DVR_WrapperRecordStatus_t s;
1394 int error;
1395
1396 DVR_RETURN_IF_FALSE(rec);
1397 DVR_RETURN_IF_FALSE(status);
1398
1399 ctx = ctx_getRecord((unsigned long)rec);
1400 DVR_RETURN_IF_FALSE(ctx);
1401
Gong Kefdb31922022-06-17 17:11:16 +08001402 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001403
Wentao MA96f68962022-06-15 19:45:35 +08001404 DVR_WRAPPER_INFO("get record(sn:%ld) status ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001405 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001406
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001407 error = process_generateRecordStatus(ctx, &s);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001408
Wentao MA96f68962022-06-15 19:45:35 +08001409 DVR_WRAPPER_INFO("record(sn:%ld) state/time/size/pkts(%d/%ld/%lld/%u) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001410 ctx->sn,
1411 s.state,
1412 s.info.time,
1413 s.info.size,
1414 s.info.pkts,
1415 error);
1416
1417 *status = s;
1418
Gong Kefdb31922022-06-17 17:11:16 +08001419 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001420
1421 return error;
1422}
1423
hualing chen4fe3bee2020-10-23 13:58:52 +08001424int dvr_wrapper_record_is_secure_mode(DVR_WrapperRecord_t rec)
1425{
1426 DVR_WrapperCtx_t *ctx;
1427 int error;
1428
1429 DVR_RETURN_IF_FALSE(rec);
1430
1431 ctx = ctx_getRecord((unsigned long)rec);
1432 DVR_RETURN_IF_FALSE(ctx);
1433
Gong Kefdb31922022-06-17 17:11:16 +08001434 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen4fe3bee2020-10-23 13:58:52 +08001435 error = dvr_record_is_secure_mode(ctx->record.recorder);
Gong Kefdb31922022-06-17 17:11:16 +08001436 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen4fe3bee2020-10-23 13:58:52 +08001437 return error;
1438}
1439
hualing chen266b9502020-04-04 17:39:39 +08001440int dvr_wrapper_set_record_secure_buffer (DVR_WrapperRecord_t rec, uint8_t *p_secure_buf, uint32_t len)
1441{
1442 DVR_WrapperCtx_t *ctx;
1443 int error;
1444
1445 DVR_RETURN_IF_FALSE(rec);
1446 DVR_RETURN_IF_FALSE(p_secure_buf);
1447
1448 ctx = ctx_getRecord((unsigned long)rec);
1449 DVR_RETURN_IF_FALSE(ctx);
1450
Gong Kefdb31922022-06-17 17:11:16 +08001451 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001452 error = dvr_record_set_secure_buffer(ctx->record.recorder, p_secure_buf, len);
Gong Kefdb31922022-06-17 17:11:16 +08001453 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001454 return error;
1455}
1456
1457int dvr_wrapper_set_record_decrypt_callback (DVR_WrapperRecord_t rec, DVR_CryptoFunction_t func, void *userdata)
1458{
1459 DVR_WrapperCtx_t *ctx;
1460 int error;
1461
1462 DVR_RETURN_IF_FALSE(rec);
1463 DVR_RETURN_IF_FALSE(func);
1464
1465 ctx = ctx_getRecord((unsigned long)rec);
1466 DVR_RETURN_IF_FALSE(ctx);
1467
Gong Kefdb31922022-06-17 17:11:16 +08001468 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001469 error = dvr_record_set_encrypt_callback(ctx->record.recorder, func, userdata);
Gong Kefdb31922022-06-17 17:11:16 +08001470 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08001471 return error;
1472}
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001473
1474
1475int dvr_wrapper_open_playback (DVR_WrapperPlayback_t *playback, DVR_WrapperPlaybackOpenParams_t *params)
1476{
1477 DVR_WrapperCtx_t *ctx;
1478 DVR_PlaybackOpenParams_t open_param;
1479 int error;
1480
1481 DVR_RETURN_IF_FALSE(playback);
1482 DVR_RETURN_IF_FALSE(params);
1483 DVR_RETURN_IF_FALSE(params->playback_handle);
1484
1485 /*get a free ctx*/
1486 ctx = ctx_getPlayback(0);
1487 DVR_RETURN_IF_FALSE(ctx);
1488
Gong Kefdb31922022-06-17 17:11:16 +08001489 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001490
Wentao MA96f68962022-06-15 19:45:35 +08001491 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 +08001492
1493 ctx_reset(ctx);
1494
1495 ctx->playback.param_open = *params;
1496 ctx->playback.event_fn = params->event_fn;
1497 ctx->playback.event_userdata = params->event_userdata;
1498 ctx->current_segment_id = 0;
1499 INIT_LIST_HEAD(&ctx->segments);
1500 ctx->sn = get_sn();
1501
1502 wrapper_requestThreadFor(ctx);
1503
hualing chen266b9502020-04-04 17:39:39 +08001504 memset(&open_param, 0, sizeof(DVR_PlaybackOpenParams_t));
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001505 open_param.dmx_dev_id = params->dmx_dev_id;
1506 open_param.block_size = params->block_size;
1507 open_param.is_timeshift = params->is_timeshift;
1508 //open_param.notification_size = 10*1024; //not supported
1509 open_param.event_fn = wrapper_playback_event_handler;
1510 open_param.event_userdata = (void*)ctx->sn;
1511 /*open_param.has_pids = 0;*/
hualing chene3797f02021-01-13 14:53:28 +08001512 open_param.is_notify_time = params->is_notify_time;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001513 open_param.player_handle = (am_tsplayer_handle)params->playback_handle;
hualing chen90b3ae62021-03-30 10:49:28 +08001514 open_param.vendor = params->vendor;
1515
Yahui Han1fbf3292021-11-08 18:17:19 +08001516 if (params->keylen) {
1517 open_param.clearkey = params->clearkey;
1518 open_param.cleariv = params->cleariv;
1519 open_param.keylen = params->keylen;
1520 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001521
1522 error = dvr_playback_open(&ctx->playback.player, &open_param);
1523 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001524 DVR_WRAPPER_INFO("playback(dmx:%d) openned fail(error:%d).\n", params->dmx_dev_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001525 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001526 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001527 wrapper_releaseThreadForType(ctx->type);
1528 return DVR_FAILURE;
1529 }
1530 if (params->is_timeshift)
1531 sn_timeshift_playback = ctx->sn;
1532
Wentao MA96f68962022-06-15 19:45:35 +08001533 DVR_WRAPPER_INFO("hanyh: playback(dmx:%d) openned ok(sn:%ld).\n", params->dmx_dev_id, ctx->sn);
hualing chen266b9502020-04-04 17:39:39 +08001534 error = dvr_playback_set_decrypt_callback(ctx->playback.player, params->crypto_fn, params->crypto_data);
1535 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08001536 DVR_WRAPPER_INFO("playback set deccrypt callback fail(error:%d).\n", error);
hualing chen266b9502020-04-04 17:39:39 +08001537 }
Gong Kefdb31922022-06-17 17:11:16 +08001538 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001539
1540 *playback = (DVR_WrapperPlayback_t)ctx->sn;
1541 return DVR_SUCCESS;
1542}
1543
1544int dvr_wrapper_close_playback (DVR_WrapperPlayback_t playback)
1545{
1546 DVR_WrapperCtx_t *ctx;
1547 int error;
1548
1549 DVR_RETURN_IF_FALSE(playback);
1550
1551 ctx = ctx_getPlayback((unsigned long)playback);
1552 DVR_RETURN_IF_FALSE(ctx);
1553
Gong Kefdb31922022-06-17 17:11:16 +08001554 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001555 DVR_WRAPPER_INFO("close playback(sn:%ld)\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08001556 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001557
1558 if (ctx->playback.param_open.is_timeshift)
1559 sn_timeshift_playback = 0;
1560
1561 /*try stop first*/
1562 error = dvr_playback_stop(ctx->playback.player, DVR_TRUE);
1563
1564 {
1565 /*remove all segments*/
1566 DVR_WrapperPlaybackSegmentInfo_t *pseg;
1567
1568 list_for_each_entry(pseg, &ctx->segments, head) {
1569 error = dvr_playback_remove_segment(ctx->playback.player, pseg->playback_info.segment_id);
Wentao MA96f68962022-06-15 19:45:35 +08001570 DVR_WRAPPER_INFO("playback(sn:%ld) remove seg(%lld) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001571 ctx->sn, pseg->playback_info.segment_id, error);
1572 }
1573 ctx_freeSegments(ctx);
1574 }
1575
1576 error = dvr_playback_close(ctx->playback.player);
1577
Wentao MA96f68962022-06-15 19:45:35 +08001578 DVR_WRAPPER_INFO("playback(sn:%ld) closed.\n", ctx->sn);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001579 ctx_reset(ctx);
Gong Kefdb31922022-06-17 17:11:16 +08001580 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001581
1582 wrapper_releaseThreadForType(ctx->type);
1583
1584 return error;
1585}
1586
1587int dvr_wrapper_start_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackFlag_t flags, DVR_PlaybackPids_t *p_pids)
1588{
1589 DVR_WrapperCtx_t *ctx;
Wentao MA9aa0aa02021-12-23 18:30:17 +08001590 int error=0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001591 uint64_t *p_segment_ids;
1592 uint32_t segment_nb;
1593 uint32_t i;
1594 DVR_RecordSegmentInfo_t seg_info_1st;
Wentao MA9aa0aa02021-12-23 18:30:17 +08001595 int got_1st_seg=0;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001596 DVR_WrapperCtx_t *ctx_record;/*for timeshift*/
hualing chenc110f952021-01-18 11:25:37 +08001597 DVR_Bool_t is_timeshift = DVR_FALSE;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001598
1599 DVR_RETURN_IF_FALSE(playback);
1600 DVR_RETURN_IF_FALSE(p_pids);
1601
hualing chenc110f952021-01-18 11:25:37 +08001602 ctx_record = NULL;
1603
1604 /*lock the recorder to avoid changing the recording segments*/
1605 ctx_record = ctx_getRecord(sn_timeshift_record);
1606
1607 if (ctx_record) {
Gong Kefdb31922022-06-17 17:11:16 +08001608 wrapper_mutex_lock(&ctx_record->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001609 if (!ctx_valid(ctx_record)
1610 || ctx_record->sn != sn_timeshift_record) {
Wentao MA96f68962022-06-15 19:45:35 +08001611 DVR_WRAPPER_INFO("timeshift, record is not for timeshifting, FATAL error found\n");
Gong Kefdb31922022-06-17 17:11:16 +08001612 wrapper_mutex_unlock(&ctx_record->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001613 is_timeshift = DVR_FALSE;
1614 } else {
1615 is_timeshift = DVR_TRUE;
1616 }
1617 }
1618
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001619 ctx = ctx_getPlayback((unsigned long)playback);
1620 DVR_RETURN_IF_FALSE(ctx);
1621
Gong Kefdb31922022-06-17 17:11:16 +08001622 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001623
Wentao MA96f68962022-06-15 19:45:35 +08001624 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 +08001625 ctx->sn,
1626 ctx->playback.param_open.location,
1627 flags,
1628 p_pids->video.pid, p_pids->video.format,
1629 p_pids->audio.pid, p_pids->audio.format,
1630 p_pids->ad.pid, p_pids->ad.format,
1631 p_pids->subtitle.pid, p_pids->subtitle.format,
1632 p_pids->pcr.pid);
1633
Gong Kefdb31922022-06-17 17:11:16 +08001634 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001635
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001636 if (ctx->playback.param_open.is_timeshift) {
1637 /*lock the recorder to avoid changing the recording segments*/
hualing chenc110f952021-01-18 11:25:37 +08001638 if (is_timeshift == DVR_FALSE) {
Wentao MA96f68962022-06-15 19:45:35 +08001639 DVR_WRAPPER_INFO("timeshift, record is not for timeshifting, FATAL error return\n");
Gong Kefdb31922022-06-17 17:11:16 +08001640 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chenc110f952021-01-18 11:25:37 +08001641 return DVR_FAILURE;
1642 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001643 DVR_WRAPPER_INFO("playback(sn:%ld) record(sn:%ld) locked ok due to timeshift\n",
hualing chenc110f952021-01-18 11:25:37 +08001644 ctx->sn, ctx_record->sn);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001645 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001646 }
1647
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001648 /*obtain all segments in a list*/
1649 segment_nb = 0;
1650 p_segment_ids = NULL;
1651 error = dvr_segment_get_list(ctx->playback.param_open.location, &segment_nb, &p_segment_ids);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001652 if (!error) {
1653 got_1st_seg = 0;
hualing chenb9a02922021-12-14 11:29:47 +08001654 struct list_head info_list; /**< segment list head*/
1655 INIT_LIST_HEAD(&info_list);
1656
Wentao MA96f68962022-06-15 19:45:35 +08001657 DVR_WRAPPER_INFO("get list segment_nb::%d",segment_nb);
hualing chenb9a02922021-12-14 11:29:47 +08001658 //we need free info list buf when we used end.
1659 error = dvr_segment_get_allInfo(ctx->playback.param_open.location, &info_list);
hualing chen926a8ec2021-12-20 20:38:24 +08001660 if (error == DVR_FAILURE) {
hualing chenb9a02922021-12-14 11:29:47 +08001661 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08001662 DVR_WRAPPER_INFO("fail to get all seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chenb9a02922021-12-14 11:29:47 +08001663 ctx->playback.param_open.location, p_segment_ids[i], error);
1664 for (i = 0; i < segment_nb; i++) {
1665 DVR_RecordSegmentInfo_t seg_info;
1666 DVR_PlaybackSegmentFlag_t flags;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001667
hualing chenb9a02922021-12-14 11:29:47 +08001668 error = dvr_segment_get_info(ctx->playback.param_open.location, p_segment_ids[i], &seg_info);
1669 if (error) {
1670 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08001671 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chenb9a02922021-12-14 11:29:47 +08001672 ctx->playback.param_open.location, p_segment_ids[i], error);
1673 break;
1674 }
1675 //add check if has audio or video pid. if not exist. not add segment to playback
1676 int ii = 0;
1677 int has_av = 0;
1678 for (ii = 0; ii < seg_info.nb_pids; ii++) {
1679 int type = (seg_info.pids[ii].type >> 24) & 0x0f;
1680 if (type == DVR_STREAM_TYPE_VIDEO ||
1681 type == DVR_STREAM_TYPE_AUDIO ||
1682 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001683 DVR_WRAPPER_INFO("success to get seg av info \n");
1684 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 +08001685 DVR_STREAM_TYPE_VIDEO,
1686 DVR_STREAM_TYPE_AUDIO,
1687 DVR_STREAM_TYPE_AD);
1688 has_av = 1;
1689 //break;
1690 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001691 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 +08001692 DVR_STREAM_TYPE_VIDEO,
1693 DVR_STREAM_TYPE_AUDIO,
1694 DVR_STREAM_TYPE_AD);
1695 }
1696 }
1697 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001698 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001699 continue;
1700 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001701 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001702 }
1703 flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
1704 error = wrapper_addPlaybackSegment(ctx, &seg_info, p_pids, flags);
1705 if (error)
1706 break;
1707 /*copy the 1st segment*/
1708 if (got_1st_seg == 0) {
1709 seg_info_1st = seg_info;
1710 got_1st_seg = 1;
1711 }
1712 }
1713 } else {
1714 for (i = 0; i < segment_nb; i++) {
1715 DVR_RecordSegmentInfo_t *seg_info;
1716 DVR_PlaybackSegmentFlag_t flags;
1717 int found = 0;
1718 list_for_each_entry(seg_info, &info_list, head)
1719 {
hualing chen8aed9582021-12-24 17:59:56 +08001720 if (seg_info->id == p_segment_ids[i]) {
hualing chenb9a02922021-12-14 11:29:47 +08001721 found = 1;
Wentao MA96f68962022-06-15 19:45:35 +08001722 DVR_WRAPPER_INFO("get segment info::%d", i);
hualing chenb9a02922021-12-14 11:29:47 +08001723 break;
1724 }
1725 }
1726 if (!found) {
hualing chen8aed9582021-12-24 17:59:56 +08001727 //last info is not found if when recording occured power off.
1728 if (p_segment_ids[i] == segment_nb - 1) {
1729 DVR_RecordSegmentInfo_t seg_info;
1730 DVR_PlaybackSegmentFlag_t flags;
1731
1732 error = dvr_segment_get_info(ctx->playback.param_open.location, p_segment_ids[i], &seg_info);
1733 if (error) {
1734 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08001735 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chen8aed9582021-12-24 17:59:56 +08001736 ctx->playback.param_open.location, p_segment_ids[i], error);
1737 break;
1738 }
1739 //
1740 //add check if has audio or video pid. if not exist. not add segment to playback
1741 int ii = 0;
1742 int has_av = 0;
1743 for (ii = 0; ii < seg_info.nb_pids; ii++) {
1744 int type = (seg_info.pids[ii].type >> 24) & 0x0f;
1745 if (type == DVR_STREAM_TYPE_VIDEO ||
1746 type == DVR_STREAM_TYPE_AUDIO ||
1747 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001748 DVR_WRAPPER_INFO("success to get seg av info \n");
1749 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 +08001750 DVR_STREAM_TYPE_VIDEO,
1751 DVR_STREAM_TYPE_AUDIO,
1752 DVR_STREAM_TYPE_AD);
1753 has_av = 1;
1754 //break;
1755 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001756 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 +08001757 DVR_STREAM_TYPE_VIDEO,
1758 DVR_STREAM_TYPE_AUDIO,
1759 DVR_STREAM_TYPE_AD);
1760 }
1761 }
1762 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001763 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chen8aed9582021-12-24 17:59:56 +08001764 continue;
1765 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001766 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chen8aed9582021-12-24 17:59:56 +08001767 }
1768 flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
1769 error = wrapper_addPlaybackSegment(ctx, &seg_info, p_pids, flags);
1770 if (error)
1771 break;
1772 }
hualing chenb9a02922021-12-14 11:29:47 +08001773 continue;
1774 }
1775
1776 //add check if has audio or video pid. if not exist. not add segment to playback
1777 int ii = 0;
1778 int has_av = 0;
1779 for (ii = 0; ii < seg_info->nb_pids; ii++) {
1780 int type = (seg_info->pids[ii].type >> 24) & 0x0f;
1781 if (type == DVR_STREAM_TYPE_VIDEO ||
1782 type == DVR_STREAM_TYPE_AUDIO ||
1783 type == DVR_STREAM_TYPE_AD) {
Wentao MA96f68962022-06-15 19:45:35 +08001784 DVR_WRAPPER_INFO("success to get seg av info \n");
1785 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 +08001786 DVR_STREAM_TYPE_VIDEO,
1787 DVR_STREAM_TYPE_AUDIO,
1788 DVR_STREAM_TYPE_AD);
1789 has_av = 1;
1790 //break;
1791 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001792 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 +08001793 DVR_STREAM_TYPE_VIDEO,
1794 DVR_STREAM_TYPE_AUDIO,
1795 DVR_STREAM_TYPE_AD);
1796 }
1797 }
1798 if (has_av == 0) {
Wentao MA96f68962022-06-15 19:45:35 +08001799 DVR_WRAPPER_INFO("fail to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001800 continue;
1801 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001802 DVR_WRAPPER_INFO("success to get seg av info \n");
hualing chenb9a02922021-12-14 11:29:47 +08001803 }
1804 flags = DVR_PLAYBACK_SEGMENT_DISPLAYABLE | DVR_PLAYBACK_SEGMENT_CONTINUOUS;
1805 error = wrapper_addPlaybackSegment(ctx, seg_info, p_pids, flags);
1806 if (error)
1807 break;
1808
1809 /*copy the 1st segment*/
1810 if (got_1st_seg == 0) {
1811 seg_info_1st = *seg_info;
1812 got_1st_seg = 1;
1813 }
hualing chen92f3a142020-07-08 20:59:33 +08001814 }
hualing chenb9a02922021-12-14 11:29:47 +08001815 //free list
1816 DVR_RecordSegmentInfo_t *segment = NULL;
1817 DVR_RecordSegmentInfo_t *segment_tmp = NULL;
1818 list_for_each_entry_safe(segment, segment_tmp, &info_list, head)
1819 {
1820 if (segment) {
1821 list_del(&segment->head);
1822 free(segment);
1823 }
1824 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001825 }
hualing chenb9a02922021-12-14 11:29:47 +08001826
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001827 free(p_segment_ids);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001828
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001829 /* return if no segment or fail to add */
1830 if (!error && got_1st_seg) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001831
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001832 /*copy the obsolete infomation, must for timeshifting*/
1833 if (ctx->playback.param_open.is_timeshift && ctx_record) {
1834 ctx->playback.obsolete = ctx_record->record.obsolete;
1835 }
1836
Wentao MA96f68962022-06-15 19:45:35 +08001837 DVR_WRAPPER_INFO("playback(sn:%ld) (%d) segments added\n", ctx->sn, i);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001838
1839 ctx->playback.reach_end = DVR_FALSE;
1840 if ((flags&DVR_PLAYBACK_STARTED_PAUSEDLIVE) == DVR_PLAYBACK_STARTED_PAUSEDLIVE)
1841 ctx->playback.speed = 0.0f;
1842 else
1843 ctx->playback.speed = 100.0f;
1844
1845 ctx->playback.pids_req = *p_pids;
hualing chen03fd4942021-07-15 15:56:41 +08001846 //calualte segment id and pos
1847 if (dvr_playback_check_limit(ctx->playback.player)) {
Gong Kefdb31922022-06-17 17:11:16 +08001848 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001849 dvr_wrapper_seek_playback(playback, 0);
Gong Kefdb31922022-06-17 17:11:16 +08001850 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08001851 error = dvr_playback_start(ctx->playback.player, flags);
1852 } else {
1853 error = dvr_playback_seek(ctx->playback.player, seg_info_1st.id, 0);
1854 error = dvr_playback_start(ctx->playback.player, flags);
Wentao MA96f68962022-06-15 19:45:35 +08001855 DVR_WRAPPER_INFO("playback(sn:%ld) seek(seg:%llu 0) for start (%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08001856 ctx->sn, seg_info_1st.id, error);
1857 }
Wentao MA96f68962022-06-15 19:45:35 +08001858 DVR_WRAPPER_INFO("playback(sn:%ld) started (%d)\n", ctx->sn, error);
hualing chen451c8f72022-03-09 13:05:52 +08001859 } else {
Wentao MA96f68962022-06-15 19:45:35 +08001860 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 +08001861 }
1862 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001863
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001864 if (ctx->playback.param_open.is_timeshift) {
1865 /*unlock the recorder locked above*/
1866 if (ctx_record && ctx_valid(ctx_record)) {
Gong Kefdb31922022-06-17 17:11:16 +08001867 wrapper_mutex_unlock(&ctx_record->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001868 DVR_WRAPPER_INFO("playback(sn:%ld), record(sn:%ld) unlocked ok due to timeshift\n",
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08001869 ctx->sn, ctx_record->sn);
1870 }
1871 }
Gong Kefdb31922022-06-17 17:11:16 +08001872 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001873
1874 return error;
1875}
hualing chen002e5b92022-02-23 17:51:21 +08001876//stop record and playback
1877int dvr_wrapper_stop_timeshift (DVR_WrapperPlayback_t playback)
1878{
1879 DVR_WrapperCtx_t *ctx_record = NULL;/*for timeshift*/
1880 int error;
Wentao MA96f68962022-06-15 19:45:35 +08001881 DVR_WRAPPER_INFO("stop timeshift record\n");
hualing chen002e5b92022-02-23 17:51:21 +08001882
1883 //stop timeshift record
1884 ctx_record = ctx_getRecord(sn_timeshift_record);
1885 error = dvr_wrapper_stop_record((DVR_WrapperRecord_t)sn_timeshift_record);
1886
Wentao MA96f68962022-06-15 19:45:35 +08001887 DVR_WRAPPER_INFO("stop timeshift ...stop play\n");
hualing chen002e5b92022-02-23 17:51:21 +08001888 //stop play
1889 error = dvr_wrapper_stop_playback(playback);
1890 //del timeshift file
1891 if (ctx_record != NULL) {
Wentao MA96f68962022-06-15 19:45:35 +08001892 DVR_WRAPPER_INFO("del timeshift(sn:%ld) ...3\n", ctx_record->sn);
hualing chen002e5b92022-02-23 17:51:21 +08001893 error = dvr_segment_del_by_location(ctx_record->record.param_open.location);
1894 }
1895 return error;
1896}
1897//start record and start playback
1898int dvr_wrapper_restart_timeshift(DVR_WrapperPlayback_t playback, DVR_PlaybackFlag_t flags, DVR_PlaybackPids_t *p_pids)
1899{
1900 DVR_WrapperCtx_t *ctx;
1901 DVR_RecordStartParams_t *start_param;
1902 int error;
1903
1904 ctx = ctx_getRecord((unsigned long)sn_timeshift_record);
1905 DVR_RETURN_IF_FALSE(ctx);
1906
Gong Kefdb31922022-06-17 17:11:16 +08001907 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001908 DVR_WRAPPER_INFO("restart record(sn:%ld, location:%s)...\n", ctx->sn, ctx->record.param_open.location);
Gong Kefdb31922022-06-17 17:11:16 +08001909 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen002e5b92022-02-23 17:51:21 +08001910
hualing chen451c8f72022-03-09 13:05:52 +08001911 {
1912 //clear old record status
1913 // struct {
1914 // DVR_WrapperRecordOpenParams_t param_open;
1915 // DVR_RecordStartParams_t param_start;
1916 // DVR_RecordStartParams_t param_update;
1917 // DVR_RecordHandle_t recorder;
1918 // DVR_RecordEventFunction_t event_fn;
1919 // void *event_userdata;
1920
1921 // /*total status = seg_status + status + obsolete*/
1922 // DVR_RecordStatus_t seg_status; /**<status of current segment*/
1923 // DVR_WrapperRecordStatus_t status; /**<status of remaining segments*/
1924 // uint64_t next_segment_id;
1925
1926 // DVR_WrapperInfo_t obsolete; /**<data obsolete due to the max limit*/
1927 // } record;
1928 memset(&(ctx->record.seg_status), 0, sizeof(DVR_RecordStatus_t));
1929 memset(&(ctx->record.status), 0, sizeof(DVR_WrapperRecordStatus_t));
1930 memset(&(ctx->record.obsolete), 0, sizeof(DVR_WrapperInfo_t));
1931 }
1932
hualing chen002e5b92022-02-23 17:51:21 +08001933 start_param = &ctx->record.param_start;
1934
1935 error = dvr_record_start_segment(ctx->record.recorder, start_param);
1936 {
1937 DVR_RecordSegmentInfo_t new_seg_info =
1938 { .id = start_param->segment.segment_id, };
1939 wrapper_addRecordSegment(ctx, &new_seg_info);
Wentao MA96f68962022-06-15 19:45:35 +08001940 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 +08001941 ctx->record.next_segment_id = start_param->segment.segment_id + 1;
1942 DVR_RecordStartParams_t *update_param;
1943 update_param = &ctx->record.param_update;
1944 memcpy(update_param, start_param, sizeof(*update_param));
1945 int i = 0;
1946 for (i = 0; i < update_param->segment.nb_pids; i++)
1947 update_param->segment.pid_action[i] = DVR_RECORD_PID_KEEP;
hualing chen002e5b92022-02-23 17:51:21 +08001948 }
1949
Wentao MA96f68962022-06-15 19:45:35 +08001950 DVR_WRAPPER_INFO("re record(sn:%ld) started = (%d)\n", ctx->sn, error);
hualing chen002e5b92022-02-23 17:51:21 +08001951
Gong Kefdb31922022-06-17 17:11:16 +08001952 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen002e5b92022-02-23 17:51:21 +08001953
1954 //start play
Wentao MA96f68962022-06-15 19:45:35 +08001955 DVR_WRAPPER_INFO("re start play and clear old status\n");
hualing chen451c8f72022-03-09 13:05:52 +08001956 //clear play statue
1957 ctx = ctx_getPlayback((unsigned long)playback);
1958 if (ctx) {
1959 //clear old playback status
1960 // struct {
1961 // DVR_WrapperPlaybackOpenParams_t param_open;
1962 // DVR_PlaybackHandle_t player;
1963 // DVR_PlaybackEventFunction_t event_fn;
1964 // void *event_userdata;
1965
1966 // /*total status = seg_status + status*/
1967 // DVR_PlaybackStatus_t seg_status;
1968 // DVR_WrapperPlaybackStatus_t status;
1969 // DVR_PlaybackPids_t pids_req;
1970 // DVR_PlaybackEvent_t last_event;
1971 // float speed;
1972 // DVR_Bool_t reach_end;
1973
1974 // DVR_WrapperInfo_t obsolete;
1975 // DVR_Bool_t tf_full;
1976 // } playback;
1977 ctx->playback.tf_full == DVR_FALSE;
1978 ctx->playback.reach_end == DVR_FALSE;
1979 memset(&(ctx->playback.last_event), 0, sizeof(DVR_PlaybackEvent_t));
1980 memset(&(ctx->playback.seg_status), 0, sizeof(DVR_PlaybackStatus_t));
1981 memset(&(ctx->playback.status), 0, sizeof(DVR_WrapperPlaybackStatus_t));
1982 memset(&(ctx->playback.obsolete), 0, sizeof(DVR_WrapperInfo_t));
1983 }
hualing chen002e5b92022-02-23 17:51:21 +08001984 error = dvr_wrapper_start_playback(playback, flags, p_pids);
1985 return error;
1986}
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08001987
1988int dvr_wrapper_stop_playback (DVR_WrapperPlayback_t playback)
1989{
1990 DVR_WrapperCtx_t *ctx;
1991 int error;
1992
1993 DVR_RETURN_IF_FALSE(playback);
1994
1995 ctx = ctx_getPlayback((unsigned long)playback);
1996 DVR_RETURN_IF_FALSE(ctx);
1997
Gong Kefdb31922022-06-17 17:11:16 +08001998 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08001999 DVR_WRAPPER_INFO("stop playback(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002000 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002001
2002 error = dvr_playback_stop(ctx->playback.player, DVR_TRUE);
2003
2004 {
2005 /*remove all segments*/
2006 DVR_WrapperPlaybackSegmentInfo_t *pseg;
2007
2008 list_for_each_entry(pseg, &ctx->segments, head) {
2009 error = dvr_playback_remove_segment(ctx->playback.player, pseg->playback_info.segment_id);
Wentao MA96f68962022-06-15 19:45:35 +08002010 DVR_WRAPPER_INFO("playback(sn:%ld) remove seg(%lld) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002011 ctx->sn, pseg->playback_info.segment_id, error);
2012 }
2013 ctx_freeSegments(ctx);
2014 }
2015
Wentao MA96f68962022-06-15 19:45:35 +08002016 DVR_WRAPPER_INFO("playback(sn:%ld) stopped (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002017 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002018
2019 return error;
2020}
2021
2022int dvr_wrapper_pause_playback (DVR_WrapperPlayback_t playback)
2023{
2024 DVR_WrapperCtx_t *ctx;
2025 int error;
2026
2027 DVR_RETURN_IF_FALSE(playback);
2028
2029 ctx = ctx_getPlayback((unsigned long)playback);
2030 DVR_RETURN_IF_FALSE(ctx);
2031
Gong Kefdb31922022-06-17 17:11:16 +08002032 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08002033 DVR_WRAPPER_INFO("pause playback(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002034 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen36e0dfd2020-05-02 16:33:06 +08002035 //clear end event
Zhiqiang Hanb723cdb2020-05-09 11:10:29 +08002036 if (ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_END)
hualing chen36e0dfd2020-05-02 16:33:06 +08002037 ctx->playback.last_event = DVR_PLAYBACK_EVENT_TRANSITION_OK;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002038
2039 error = dvr_playback_pause(ctx->playback.player, DVR_FALSE);
2040
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002041 ctx->playback.speed = 0.0f;
2042
Wentao MA96f68962022-06-15 19:45:35 +08002043 DVR_WRAPPER_INFO("playback(sn:%ld) paused (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002044 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002045
2046 return error;
2047}
2048
2049int dvr_wrapper_resume_playback (DVR_WrapperPlayback_t playback)
2050{
2051 DVR_WrapperCtx_t *ctx;
2052 int error;
2053
2054 DVR_RETURN_IF_FALSE(playback);
2055
2056 ctx = ctx_getPlayback((unsigned long)playback);
2057 DVR_RETURN_IF_FALSE(ctx);
hualing chen03fd4942021-07-15 15:56:41 +08002058 //if set limit.we need check if seek to valid data when resume
2059 uint32_t time_offset = ctx->playback.status.info_cur.time + ctx->playback.status.info_obsolete.time;
2060 if (dvr_playback_check_limit(ctx->playback.player)) {
2061 int expired = dvr_playback_calculate_expiredlen(ctx->playback.player);
2062 if (expired > time_offset) {
Wentao MA96f68962022-06-15 19:45:35 +08002063 DVR_WRAPPER_INFO("seek before resume reset offset playback(sn:%ld) (off:%d expired:%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08002064 ctx->sn, time_offset, expired);
2065 time_offset = expired;
2066 dvr_wrapper_seek_playback(playback, time_offset);
2067 }
2068 }
Gong Kefdb31922022-06-17 17:11:16 +08002069 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08002070 DVR_WRAPPER_INFO("resume playback(sn:%ld) ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002071 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002072
2073 error = dvr_playback_resume(ctx->playback.player);
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002074 ctx->playback.speed = 100.0f;
2075
Wentao MA96f68962022-06-15 19:45:35 +08002076 DVR_WRAPPER_INFO("playback(sn:%ld) resumed (%d)\n", ctx->sn, error);
Gong Kefdb31922022-06-17 17:11:16 +08002077 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002078
2079 return error;
2080}
2081
2082int dvr_wrapper_set_playback_speed (DVR_WrapperPlayback_t playback, float speed)
2083{
2084 DVR_WrapperCtx_t *ctx;
2085 int error;
2086 DVR_PlaybackSpeed_t dvr_speed = {
2087 .speed = { speed },
2088 .mode = (speed > 0) ? DVR_PLAYBACK_FAST_FORWARD : DVR_PLAYBACK_FAST_BACKWARD
2089 };
2090
2091 DVR_RETURN_IF_FALSE(playback);
2092
2093 ctx = ctx_getPlayback((unsigned long)playback);
2094 DVR_RETURN_IF_FALSE(ctx);
2095
Gong Kefdb31922022-06-17 17:11:16 +08002096 wrapper_mutex_lock(&ctx->wrapper_lock);
Wentao MA96f68962022-06-15 19:45:35 +08002097 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 +08002098 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002099
2100 error = dvr_playback_set_speed(ctx->playback.player, dvr_speed);
2101
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002102 if (ctx->playback.speed != 0.0f && ctx->playback.speed != 100.0f
2103 && ctx->playback.last_event == DVR_PLAYBACK_EVENT_REACHED_BEGIN
2104 && ctx->playback.seg_status.state == DVR_PLAYBACK_STATE_PAUSE) {
Wentao MA96f68962022-06-15 19:45:35 +08002105 DVR_WRAPPER_INFO("x%f -> x%f, paused, do resume first\n", ctx->playback.speed, speed);
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002106 error = dvr_playback_resume(ctx->playback.player);
2107 } else if (ctx->playback.speed == 0.0f
2108 && speed != 0.0f
2109 && speed != 100.0f) {
2110 /*libdvr do not support pause with speed=0, will not be here*/
Wentao MA96f68962022-06-15 19:45:35 +08002111 DVR_WRAPPER_INFO("x%f -> x%f, do resume first\n", ctx->playback.speed, speed);
Zhiqiang Han3eb75f92020-04-08 10:07:55 +08002112 error = dvr_playback_resume(ctx->playback.player);
2113 }
2114
2115 ctx->playback.speed = speed;
2116
Wentao MA96f68962022-06-15 19:45:35 +08002117 DVR_WRAPPER_INFO("playback(sn:%ld) speeded(x%f) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002118 ctx->sn, speed, error);
Gong Kefdb31922022-06-17 17:11:16 +08002119 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002120
2121 return error;
2122}
2123
hualing chen03fd4942021-07-15 15:56:41 +08002124int dvr_wrapper_setlimit_playback (DVR_WrapperPlayback_t playback, uint64_t time, int32_t limit)
2125{
2126 DVR_WrapperCtx_t *ctx;
2127 int error;
2128
2129 DVR_RETURN_IF_FALSE(playback);
2130
2131 ctx = ctx_getPlayback((unsigned long)playback);
2132 DVR_RETURN_IF_FALSE(ctx);
2133
Gong Kefdb31922022-06-17 17:11:16 +08002134 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002135
Wentao MA96f68962022-06-15 19:45:35 +08002136 DVR_WRAPPER_INFO("setlimit playback(sn:%ld) (time:%lld limit:%d) ...\n", ctx->sn, time, limit);
Gong Kefdb31922022-06-17 17:11:16 +08002137 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002138
2139 error = dvr_playback_setlimit(ctx->playback.player, time, limit);
Wentao MA96f68962022-06-15 19:45:35 +08002140 DVR_WRAPPER_INFO("playback(sn:%ld) setlimit(time:%lld limit:%d) ...\n", ctx->sn, time, limit);
hualing chen03fd4942021-07-15 15:56:41 +08002141
Gong Kefdb31922022-06-17 17:11:16 +08002142 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen03fd4942021-07-15 15:56:41 +08002143
2144 return error;
2145}
2146
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002147int dvr_wrapper_seek_playback (DVR_WrapperPlayback_t playback, uint32_t time_offset)
2148{
2149 DVR_WrapperCtx_t *ctx;
2150 int error;
2151 DVR_WrapperPlaybackSegmentInfo_t *pseg;
2152 uint64_t segment_id;
2153 uint32_t off;
2154 uint64_t last_segment_id;
2155 uint32_t pre_off;
2156
2157 DVR_RETURN_IF_FALSE(playback);
2158
2159 ctx = ctx_getPlayback((unsigned long)playback);
2160 DVR_RETURN_IF_FALSE(ctx);
2161
Gong Kefdb31922022-06-17 17:11:16 +08002162 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002163
Wentao MA96f68962022-06-15 19:45:35 +08002164 DVR_WRAPPER_INFO("seek playback(sn:%ld) (off:%d) ...\n", ctx->sn, time_offset);
Gong Kefdb31922022-06-17 17:11:16 +08002165 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002166
2167 off = 0;
2168 segment_id = 0;
2169 pre_off = 0;
2170 last_segment_id = 0;
2171
hualing chen03fd4942021-07-15 15:56:41 +08002172 //if set limit info we need check ts data is
2173 //expired when seek
2174 if (dvr_playback_check_limit(ctx->playback.player)) {
2175 int expired = dvr_playback_calculate_expiredlen(ctx->playback.player);
2176 if (expired > time_offset) {
Wentao MA96f68962022-06-15 19:45:35 +08002177 DVR_WRAPPER_INFO("seek reset offset playback(sn:%ld) (off:%d expired:%d)\n",
hualing chen03fd4942021-07-15 15:56:41 +08002178 ctx->sn, time_offset, expired);
2179 time_offset = expired;
2180 }
2181 }
2182
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002183 list_for_each_entry_reverse(pseg, &ctx->segments, head) {
2184 segment_id = pseg->seg_info.id;
2185
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002186 if ((ctx->playback.obsolete.time + pre_off + pseg->seg_info.duration) > time_offset)
2187 break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002188
2189 last_segment_id = pseg->seg_info.id;
2190 pre_off += pseg->seg_info.duration;
2191 }
2192
2193 if (last_segment_id == segment_id) {
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002194 /*1.only one seg with id:0, 2.offset exceeds the total duration*/
2195 off = time_offset;
2196 } else if (ctx->playback.obsolete.time >= time_offset) {
2197 off = 0;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002198 } else {
hualing chenda76fc52020-05-28 14:56:42 +08002199 off = time_offset - pre_off - ctx->playback.obsolete.time;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002200 }
2201
Wentao MA96f68962022-06-15 19:45:35 +08002202 DVR_WRAPPER_INFO("seek playback(sn:%ld) (seg:%lld, off:%d)\n",
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002203 ctx->sn, segment_id, off);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002204 error = dvr_playback_seek(ctx->playback.player, segment_id, off);
Wentao MA96f68962022-06-15 19:45:35 +08002205 DVR_WRAPPER_INFO("playback(sn:%ld) seeked(off:%d) (%d)\n", ctx->sn, time_offset, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002206
Gong Kefdb31922022-06-17 17:11:16 +08002207 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002208
2209 return error;
2210}
2211
2212int dvr_wrapper_update_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackPids_t *p_pids)
2213{
2214 DVR_WrapperCtx_t *ctx;
2215 int error;
2216 DVR_WrapperPlaybackSegmentInfo_t *pseg;
2217
2218 DVR_RETURN_IF_FALSE(playback);
2219 DVR_RETURN_IF_FALSE(p_pids);
2220
2221 ctx = ctx_getPlayback((unsigned long)playback);
2222 DVR_RETURN_IF_FALSE(ctx);
2223
Gong Kefdb31922022-06-17 17:11:16 +08002224 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002225
Wentao MA96f68962022-06-15 19:45:35 +08002226 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) ...\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002227 ctx->sn,
2228 p_pids->video.pid, p_pids->video.format,
2229 p_pids->audio.pid, p_pids->audio.format);
Gong Kefdb31922022-06-17 17:11:16 +08002230 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002231
2232 ctx->playback.pids_req = *p_pids;
2233
2234 error = 0;
2235 list_for_each_entry_reverse(pseg, &ctx->segments, head) {
2236 /*should update the whole list of segments*/
2237 /*if (pseg->seg_info.id == ctx->current_segment_id)*/ {
2238 /*list_for_each_entry_from(pseg, &ctx->segments, head)*/ {
2239 /*check udpate for pids*/
2240 if (memcmp(&pseg->playback_info.pids, p_pids, sizeof(*p_pids)) != 0) {
2241 pseg->playback_info.pids = *p_pids;
2242 error = dvr_playback_update_segment_pids(ctx->playback.player, pseg->seg_info.id, p_pids);
2243 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08002244 DVR_WRAPPER_INFO("failed to playback(sn:%ld) update segment(id:%lld) pids (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002245 ctx->sn, pseg->seg_info.id, error);
2246 /*do not break, let list updated*/
2247 }
2248 }
2249 }
2250 /*break;*/
2251 }
2252 }
2253
Wentao MA96f68962022-06-15 19:45:35 +08002254 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002255 ctx->sn,
2256 p_pids->video.pid, p_pids->video.format,
2257 p_pids->audio.pid, p_pids->audio.format,
2258 error);
2259
Gong Kefdb31922022-06-17 17:11:16 +08002260 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002261
2262 return error;
2263}
2264
hualing chena5f03222021-12-02 11:22:35 +08002265int dvr_wrapper_only_update_playback (DVR_WrapperPlayback_t playback, DVR_PlaybackPids_t *p_pids)
2266{
2267 DVR_WrapperCtx_t *ctx;
2268 int error;
2269 DVR_WrapperPlaybackSegmentInfo_t *pseg;
2270
2271 DVR_RETURN_IF_FALSE(playback);
2272 DVR_RETURN_IF_FALSE(p_pids);
2273
2274 ctx = ctx_getPlayback((unsigned long)playback);
2275 DVR_RETURN_IF_FALSE(ctx);
2276
Gong Kefdb31922022-06-17 17:11:16 +08002277 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002278
Wentao MA96f68962022-06-15 19:45:35 +08002279 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) ...\n",
hualing chena5f03222021-12-02 11:22:35 +08002280 ctx->sn,
2281 p_pids->video.pid, p_pids->video.format,
2282 p_pids->audio.pid, p_pids->audio.format);
Gong Kefdb31922022-06-17 17:11:16 +08002283 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002284
2285 ctx->playback.pids_req = *p_pids;
2286
2287 error = 0;
2288 list_for_each_entry_reverse(pseg, &ctx->segments, head) {
2289 /*should update the whole list of segments*/
2290 /*if (pseg->seg_info.id == ctx->current_segment_id)*/ {
2291 /*list_for_each_entry_from(pseg, &ctx->segments, head)*/ {
2292 /*check udpate for pids*/
2293 if (memcmp(&pseg->playback_info.pids, p_pids, sizeof(*p_pids)) != 0) {
2294 pseg->playback_info.pids = *p_pids;
2295 error = dvr_playback_only_update_segment_pids(ctx->playback.player, pseg->seg_info.id, p_pids);
2296 if (error) {
Wentao MA96f68962022-06-15 19:45:35 +08002297 DVR_WRAPPER_INFO("failed to playback(sn:%ld) update segment(id:%lld) pids (%d)\n",
hualing chena5f03222021-12-02 11:22:35 +08002298 ctx->sn, pseg->seg_info.id, error);
2299 /*do not break, let list updated*/
2300 }
2301 }
2302 }
2303 /*break;*/
2304 }
2305 }
2306
Wentao MA96f68962022-06-15 19:45:35 +08002307 DVR_WRAPPER_INFO("update playback(sn:%ld) v/a(%d:%d/%d:%d) (%d)\n",
hualing chena5f03222021-12-02 11:22:35 +08002308 ctx->sn,
2309 p_pids->video.pid, p_pids->video.format,
2310 p_pids->audio.pid, p_pids->audio.format,
2311 error);
2312
Gong Kefdb31922022-06-17 17:11:16 +08002313 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chena5f03222021-12-02 11:22:35 +08002314
2315 return error;
2316}
2317
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002318int dvr_wrapper_get_playback_status(DVR_WrapperPlayback_t playback, DVR_WrapperPlaybackStatus_t *status)
2319{
2320 DVR_WrapperCtx_t *ctx;
2321 DVR_WrapperPlaybackStatus_t s;
2322 DVR_PlaybackStatus_t play_status;
2323 int error;
2324
2325 DVR_RETURN_IF_FALSE(playback);
2326 DVR_RETURN_IF_FALSE(status);
2327
2328 ctx = ctx_getPlayback((unsigned long)playback);
2329 DVR_RETURN_IF_FALSE(ctx);
2330
Gong Kefdb31922022-06-17 17:11:16 +08002331 wrapper_mutex_lock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002332
Wentao MA96f68962022-06-15 19:45:35 +08002333 DVR_WRAPPER_INFO("get playback(sn:%ld) status ...\n", ctx->sn);
Gong Kefdb31922022-06-17 17:11:16 +08002334 WRAPPER_RETURN_IF_FALSE_WITH_UNLOCK(ctx_valid(ctx), &ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002335
2336 error = dvr_playback_get_status(ctx->playback.player, &play_status);
Wentao MA96f68962022-06-15 19:45:35 +08002337 DVR_WRAPPER_INFO("playback(sn:%ld) get status (%d)\n", ctx->sn, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002338
2339 ctx->playback.seg_status = play_status;
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002340 error = process_generatePlaybackStatus(ctx, &s);
2341
hualing chenb5cd42e2020-04-15 17:03:34 +08002342 if (ctx->playback.reach_end == DVR_TRUE && ctx->playback.param_open.is_timeshift == DVR_FALSE) {
2343 //reach end need set full time to cur.so app can exist playback.
Wentao MA96f68962022-06-15 19:45:35 +08002344 DVR_WRAPPER_INFO("set cur time to full time, reach end occur");
hualing chenb5cd42e2020-04-15 17:03:34 +08002345 s.info_cur.time = s.info_full.time;
2346 }
Wentao MA96f68962022-06-15 19:45:35 +08002347 DVR_WRAPPER_INFO("playback(sn:%ld) state/cur/full/obsl(%d/%ld/%ld/%ld) (%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002348 ctx->sn,
2349 s.state,
2350 s.info_cur.time,
2351 s.info_full.time,
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002352 s.info_obsolete.time,
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002353 error);
2354
2355 *status = s;
2356
Gong Kefdb31922022-06-17 17:11:16 +08002357 wrapper_mutex_unlock(&ctx->wrapper_lock);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002358
2359 return error;
2360}
2361
hualing chen266b9502020-04-04 17:39:39 +08002362int dvr_wrapper_set_playback_secure_buffer (DVR_WrapperPlayback_t playback, uint8_t *p_secure_buf, uint32_t len)
2363{
2364 DVR_WrapperCtx_t *ctx;
2365 int error;
2366
2367 DVR_RETURN_IF_FALSE(playback);
2368 DVR_RETURN_IF_FALSE(p_secure_buf);
2369
2370 ctx = ctx_getPlayback((unsigned long)playback);
2371 DVR_RETURN_IF_FALSE(ctx);
2372
Gong Kefdb31922022-06-17 17:11:16 +08002373 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002374 error = dvr_playback_set_secure_buffer(ctx->playback.player, p_secure_buf, len);
Gong Kefdb31922022-06-17 17:11:16 +08002375 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002376 return error;
2377}
2378
2379int dvr_wrapper_set_playback_decrypt_callback (DVR_WrapperPlayback_t playback, DVR_CryptoFunction_t func, void *userdata)
2380{
2381 DVR_WrapperCtx_t *ctx;
2382 int error;
2383
2384 DVR_RETURN_IF_FALSE(playback);
2385 DVR_RETURN_IF_FALSE(func);
2386
2387 ctx = ctx_getPlayback((unsigned long)playback);
2388 DVR_RETURN_IF_FALSE(ctx);
2389
Gong Kefdb31922022-06-17 17:11:16 +08002390 wrapper_mutex_lock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002391 error = dvr_playback_set_decrypt_callback(ctx->playback.player, func, userdata);
Gong Kefdb31922022-06-17 17:11:16 +08002392 wrapper_mutex_unlock(&ctx->wrapper_lock);
hualing chen266b9502020-04-04 17:39:39 +08002393 return error;
2394}
2395
Zhiqiang Han620b9252021-11-09 14:23:20 +08002396int dvr_wrapper_segment_del_by_location (const char *location)
2397{
2398 char fpath[DVR_MAX_LOCATION_SIZE];
2399
2400 DVR_RETURN_IF_FALSE(location);
2401
2402 /*del the stats file*/
2403 sprintf(fpath, "%s.stats", location);
2404 unlink(fpath);
2405
2406 return dvr_segment_del_by_location(location);
2407}
2408
2409int dvr_wrapper_segment_get_info_by_location (const char *location, DVR_WrapperInfo_t *p_info)
2410{
2411 FILE *fp;
2412 char fpath[DVR_MAX_LOCATION_SIZE];
2413
2414 DVR_RETURN_IF_FALSE(location);
2415 DVR_RETURN_IF_FALSE(p_info);
2416
2417 if (p_info)
2418 memset(p_info, 0, sizeof(p_info[0]));
2419
2420 memset(fpath, 0, sizeof(fpath));
2421 sprintf(fpath, "%s.stats", location);
2422
2423 /*stats file exists*/
2424 if ((fp = fopen(fpath, "r"))) {
2425 char buf[256];
2426
2427 if (fgets(buf, sizeof(buf), fp) != NULL
2428 && (sscanf(buf, ":%llu:%lu:%u",
2429 &p_info->size,
2430 &p_info->time,
2431 &p_info->pkts) == 3)) {
2432 fclose(fp);
Wentao MA96f68962022-06-15 19:45:35 +08002433 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 +08002434 return DVR_SUCCESS;
2435 }
Zhiqiang Hanb9785922021-11-26 18:47:39 +08002436 fclose(fp);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002437 }
2438
2439 /*fallback, slow on mass files*/
Wentao MA96f68962022-06-15 19:45:35 +08002440 DVR_WRAPPER_INFO("rec '%s.stats' invalid.\n", location);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002441
2442 int error;
2443 uint32_t n_ids;
2444 uint64_t *p_ids;
Zhiqiang Han620b9252021-11-09 14:23:20 +08002445
hualing chen8aed9582021-12-24 17:59:56 +08002446 error = dvr_segment_get_list(location, &n_ids, &p_ids);
hualing chenb9a02922021-12-14 11:29:47 +08002447
Zhiqiang Han620b9252021-11-09 14:23:20 +08002448 if (!error) {
2449 int i;
hualing chenb9a02922021-12-14 11:29:47 +08002450 struct list_head info_list; /**< segment list head*/
2451 INIT_LIST_HEAD(&info_list);
2452
2453 //we need free info list buf when we used end.
hualing chen8aed9582021-12-24 17:59:56 +08002454 error = dvr_segment_get_allInfo(location, &info_list);
2455 if (error == DVR_FAILURE) {
hualing chenb9a02922021-12-14 11:29:47 +08002456 DVR_RecordSegmentInfo_t info;
2457
2458 memset(&info, 0, sizeof(info));
2459 error = DVR_FAILURE;
Wentao MA96f68962022-06-15 19:45:35 +08002460 DVR_WRAPPER_INFO("fail to get seg info (location:%s, seg:%llu), (error:%d)\n",
hualing chen8aed9582021-12-24 17:59:56 +08002461 location, 0, error);
hualing chenb9a02922021-12-14 11:29:47 +08002462
2463 for (i = 0; i < n_ids; i++) {
hualing chen8aed9582021-12-24 17:59:56 +08002464 error = dvr_segment_get_info(location, p_ids[i], &info);
hualing chenb9a02922021-12-14 11:29:47 +08002465 if (!error) {
2466 p_info->size += info.size;
2467 p_info->time += info.duration;
2468 p_info->pkts += info.nb_packets;
2469 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002470 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chenb9a02922021-12-14 11:29:47 +08002471 break;
2472 }
2473 }
2474 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002475 DVR_WRAPPER_INFO("get list segment_nb::%d",n_ids);
hualing chenb9a02922021-12-14 11:29:47 +08002476 for (i = 0; i < n_ids; i++) {
2477
2478 DVR_RecordSegmentInfo_t *seg_info;
2479 DVR_PlaybackSegmentFlag_t flags;
2480 int found = 0;
2481 list_for_each_entry(seg_info, &info_list, head)
2482 {
hualing chen8aed9582021-12-24 17:59:56 +08002483 if (seg_info->id == p_ids[i]) {
hualing chenb9a02922021-12-14 11:29:47 +08002484 found = 1;
2485 break;
2486 }
2487 }
2488 if (!found) {
Wentao MA96f68962022-06-15 19:45:35 +08002489 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 +08002490 if (p_ids[i] == n_ids - 1) {
2491 DVR_RecordSegmentInfo_t info;
Wentao MA96f68962022-06-15 19:45:35 +08002492 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 +08002493 error = dvr_segment_get_info(location, p_ids[i], &info);
2494 if (!error) {
2495 p_info->size += info.size;
2496 p_info->time += info.duration;
2497 p_info->pkts += info.nb_packets;
2498 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002499 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chen8aed9582021-12-24 17:59:56 +08002500 break;
2501 }
2502 }
hualing chenb9a02922021-12-14 11:29:47 +08002503 continue;
2504 }
2505
2506 if (!error) {
2507 p_info->size += seg_info->size;
2508 p_info->time += seg_info->duration;
2509 p_info->pkts += seg_info->nb_packets;
2510 } else {
Wentao MA96f68962022-06-15 19:45:35 +08002511 DVR_WRAPPER_INFO("%s:%lld get seg info fail.\n", location, p_ids[i]);
hualing chenb9a02922021-12-14 11:29:47 +08002512 break;
2513 }
2514 }
2515 //free list
2516 DVR_RecordSegmentInfo_t *segment = NULL;
2517 DVR_RecordSegmentInfo_t *segment_tmp = NULL;
2518 list_for_each_entry_safe(segment, segment_tmp, &info_list, head)
2519 {
2520 if (segment) {
2521 list_del(&segment->head);
2522 free(segment);
2523 }
2524 }
2525 }
2526 free(p_ids);
Zhiqiang Hanb9785922021-11-26 18:47:39 +08002527 } else {
2528 n_ids = 0;
Zhiqiang Han620b9252021-11-09 14:23:20 +08002529 }
Wentao MA96f68962022-06-15 19:45:35 +08002530 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 +08002531
2532 return (error)? DVR_FAILURE : DVR_SUCCESS;
2533}
2534
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002535static DVR_Result_t wrapper_record_event_handler(DVR_RecordEvent_t event, void *params, void *userdata)
2536{
2537 DVR_WrapperEventCtx_t evt;
2538
2539 DVR_RETURN_IF_FALSE(userdata);
2540
2541 evt.sn = (unsigned long)userdata;
2542 evt.type = W_REC;
2543 evt.record.event = event;
2544 evt.record.status = *(DVR_RecordStatus_t *)params;
Wentao MA96f68962022-06-15 19:45:35 +08002545 DVR_WRAPPER_INFO("evt[sn:%ld, record, evt:0x%x]\n", evt.sn, evt.record.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002546 return ctx_addRecordEvent(&evt);
2547}
2548
2549static DVR_Result_t wrapper_playback_event_handler(DVR_PlaybackEvent_t event, void *params, void *userdata)
2550{
2551 DVR_WrapperEventCtx_t evt;
2552
2553 DVR_RETURN_IF_FALSE(userdata);
2554
2555 evt.sn = (unsigned long)userdata;
2556 evt.type = W_PLAYBACK;
2557 evt.playback.event = event;
2558 evt.playback.status = *(DVR_Play_Notify_t *)params;
Wentao MA96f68962022-06-15 19:45:35 +08002559 DVR_WRAPPER_INFO("evt[sn:%ld, playbck, evt:0x%x]\n", evt.sn, evt.playback.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002560 return ctx_addPlaybackEvent(&evt);
2561}
2562
2563static inline int process_notifyRecord(DVR_WrapperCtx_t *ctx, DVR_RecordEvent_t evt, DVR_WrapperRecordStatus_t *status)
2564{
Wentao MA96f68962022-06-15 19:45:35 +08002565 DVR_WRAPPER_INFO("notify(sn:%ld) evt(0x%x) statistic:time/size/pkts(%ld/%lld/%u) obsl:(%ld/%llu/%u)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002566 ctx->sn,
2567 evt,
2568 status->info.time,
2569 status->info.size,
2570 status->info.pkts,
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002571 status->info_obsolete.time,
2572 status->info_obsolete.size,
2573 status->info_obsolete.pkts);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002574
2575 if (ctx->record.event_fn)
2576 return ctx->record.event_fn(evt, status, ctx->record.event_userdata);
2577 return 0;
2578}
2579
Zhiqiang Han620b9252021-11-09 14:23:20 +08002580static int wrapper_saveRecordStatistics(const char *location, DVR_WrapperRecordStatus_t *p_status)
2581{
2582 FILE *fp;
2583 char fpath[DVR_MAX_LOCATION_SIZE];
2584
2585 DVR_RETURN_IF_FALSE(location);
2586 DVR_RETURN_IF_FALSE(p_status);
2587
2588 sprintf(fpath, "%s.stats", location);
2589
2590 /*stats file*/
2591 if ((fp = fopen(fpath, "w"))) {
2592 char buf[256];
2593 snprintf(buf, sizeof(buf), ":%llu:%lu:%u\n",
2594 p_status->info.size - p_status->info_obsolete.size,
2595 p_status->info.time - p_status->info_obsolete.time,
2596 p_status->info.pkts - p_status->info_obsolete.pkts);
2597 fputs(buf, fp);
2598 fclose(fp);
2599 return DVR_SUCCESS;
2600 }
2601
2602 return DVR_FAILURE;
2603}
2604
2605
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002606static inline int record_startNextSegment(DVR_WrapperCtx_t *ctx)
2607{
2608 DVR_RecordStartParams_t param;
2609 DVR_RecordSegmentInfo_t seg_info;
2610 int i;
2611 int error;
2612
2613 memcpy(&param, &ctx->record.param_update, sizeof(param));
2614 memset(&ctx->record.param_update.segment, 0, sizeof(ctx->record.param_update.segment));
2615 ctx->record.param_update.segment.segment_id = ctx->record.next_segment_id++;
2616 for (i = 0; i < param.segment.nb_pids; i++) {
2617 if (param.segment.pid_action[i] != DVR_RECORD_PID_CLOSE) {
2618 ctx->record.param_update.segment.pids[ctx->record.param_update.segment.nb_pids] = param.segment.pids[i];
2619 ctx->record.param_update.segment.pid_action[ctx->record.param_update.segment.nb_pids] = DVR_RECORD_PID_KEEP;
2620 ctx->record.param_update.segment.nb_pids++;
2621 }
2622 }
2623 error = dvr_record_next_segment(ctx->record.recorder, &ctx->record.param_update, &seg_info);
2624 {
2625 DVR_RecordSegmentInfo_t new_seg_info =
2626 { .id = ctx->record.param_update.segment.segment_id, };
2627 wrapper_updateRecordSegment(ctx, &seg_info, U_ALL);
2628 wrapper_addRecordSegment(ctx, &new_seg_info);
2629 }
2630
Wentao MA96f68962022-06-15 19:45:35 +08002631 DVR_WRAPPER_INFO("record next segment(%llu)=(%d)\n", ctx->record.param_update.segment.segment_id, error);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002632 return error;
2633}
2634
2635static inline int record_removeSegment(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordSegmentInfo_t *pseg)
2636{
2637 return wrapper_removeRecordSegment(ctx, pseg);
2638}
2639
2640/*should run periodically to update the current status*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002641static int process_generateRecordStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperRecordStatus_t *status)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002642{
2643 /*the current seg is not covered in the statistics*/
2644 DVR_WrapperRecordSegmentInfo_t *pseg;
2645
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002646 /*re-calculate the all segments*/
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002647 memset(&ctx->record.status, 0, sizeof(ctx->record.status));
2648
2649 ctx->record.status.state = ctx->record.seg_status.state;
2650 ctx->record.status.pids.nb_pids = ctx->record.seg_status.info.nb_pids;
2651 memcpy(ctx->record.status.pids.pids,
2652 ctx->record.seg_status.info.pids,
2653 sizeof(ctx->record.status.pids.pids));
2654 ctx->current_segment_id = ctx->record.seg_status.info.id;
2655
2656 list_for_each_entry_reverse(pseg, &ctx->segments, head) {
2657 if (pseg->info.id != ctx->record.seg_status.info.id) {
2658 ctx->record.status.info.time += pseg->info.duration;
2659 ctx->record.status.info.size += pseg->info.size;
2660 ctx->record.status.info.pkts += pseg->info.nb_packets;
2661 }
2662 }
2663
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002664 ctx->record.status.info_obsolete = ctx->record.obsolete;
2665
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002666 wrapper_updateRecordSegment(ctx, &ctx->record.seg_status.info, U_ALL);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002667
2668 if (status) {
2669 *status = ctx->record.status;
2670 status->info.time += ctx->record.seg_status.info.duration;
2671 status->info.size += ctx->record.seg_status.info.size;
2672 status->info.pkts += ctx->record.seg_status.info.nb_packets;
2673 }
2674
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002675 return DVR_SUCCESS;
2676}
2677
2678
2679static int process_handleRecordEvent(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
2680{
2681 DVR_WrapperRecordStatus_t status;
2682
2683 memset(&status, 0, sizeof(status));
2684
Wentao MA96f68962022-06-15 19:45:35 +08002685 DVR_WRAPPER_INFO("evt (sn:%ld) 0x%x (state:%d)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002686 evt->sn, evt->record.event, evt->record.status.state);
hualing chend3b55ab2021-05-06 09:56:27 +08002687 if (ctx->record.param_update.segment.segment_id != evt->record.status.info.id) {
Wentao MA96f68962022-06-15 19:45:35 +08002688 DVR_WRAPPER_INFO("evt (sn:%ld) cur id:0x%x (event id:%d)\n",
Gong Ke2a0ebbe2021-05-25 15:22:50 +08002689 evt->sn, (int)ctx->record.param_update.segment.segment_id, (int)evt->record.status.info.id);
hualing chend3b55ab2021-05-06 09:56:27 +08002690 return 0;
2691 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002692 switch (evt->record.event)
2693 {
2694 case DVR_RECORD_EVENT_STATUS:
2695 {
2696 switch (evt->record.status.state)
2697 {
2698 case DVR_RECORD_STATE_OPENED:
2699 case DVR_RECORD_STATE_CLOSED:
2700 {
2701 ctx->record.seg_status = evt->record.status;
2702
2703 status.state = evt->record.status.state;
2704 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002705 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002706 } break;
2707 case DVR_RECORD_STATE_STARTED:
2708 {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002709 ctx->record.seg_status = evt->record.status;
2710
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002711 process_generateRecordStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002712 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002713 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002714
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002715 /*restart to next segment*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002716 if (ctx->record.param_open.segment_size
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002717 && evt->record.status.info.size >= ctx->record.param_open.segment_size) {
Wentao MA96f68962022-06-15 19:45:35 +08002718 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 +08002719 ctx->sn,
2720 evt->record.status.info.size,
2721 ctx->record.param_open.segment_size);
Zhiqiang Hand977e972020-05-11 11:30:47 +08002722 if (record_startNextSegment(ctx) != DVR_SUCCESS) {
2723 /*should notify the recording's stop*/
2724 int error = dvr_record_close(ctx->record.recorder);
Wentao MA96f68962022-06-15 19:45:35 +08002725 DVR_WRAPPER_INFO("stop record(%lu)=%d, failed to start new segment for recording.",
Zhiqiang Hand977e972020-05-11 11:30:47 +08002726 ctx->sn, error);
2727 status.state = DVR_RECORD_STATE_CLOSED;
2728 process_notifyRecord(ctx, DVR_RECORD_EVENT_WRITE_ERROR, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002729 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Hand977e972020-05-11 11:30:47 +08002730 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002731 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002732
2733 if (ctx->record.param_open.is_timeshift
2734 && ctx->record.param_open.max_time
2735 && status.info.time >= ctx->record.param_open.max_time) {
2736 DVR_WrapperRecordSegmentInfo_t *pseg;
2737
2738 /*as the player do not support null playlist,
2739 there must be one segment existed at any time,
2740 we have to keep two segments before remove one*/
2741 pseg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
2742 if (pseg == list_first_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head)) {
2743 /*only one segment, waiting for more*/
Wentao MA96f68962022-06-15 19:45:35 +08002744 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 +08002745 status.info.size,
2746 ctx->record.param_open.max_time,
2747 ctx->record.param_open.segment_size);
2748 } else {
2749 /*timeshifting, remove the 1st segment and notify the player*/
2750 record_removeSegment(ctx, pseg);
2751
2752 process_generateRecordStatus(ctx, &status);
2753 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002754 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002755 }
2756 }
2757
2758 if (ctx->record.param_open.is_timeshift
2759 && ctx->record.param_open.max_size
2760 && status.info.size >= ctx->record.param_open.max_size) {
2761 DVR_WrapperRecordSegmentInfo_t *pseg;
2762
2763 /*as the player do not support null playlist,
2764 there must be one segment existed at any time,
2765 we have to keep two segments before remove one*/
2766 pseg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
2767 if (pseg == list_first_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head)) {
2768 /*only one segment, waiting for more*/
Wentao MA96f68962022-06-15 19:45:35 +08002769 DVR_WRAPPER_INFO("warning: the size(%lld) of record < max size of segment(%lld)\n",
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002770 status.info.size,
2771 ctx->record.param_open.segment_size);
2772 } else {
2773 record_removeSegment(ctx, pseg);
2774
2775 process_generateRecordStatus(ctx, &status);
2776 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002777 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002778 }
2779 }
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002780 } break;
2781 case DVR_RECORD_STATE_STOPPED:
2782 {
2783 ctx->record.seg_status = evt->record.status;
2784
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002785 process_generateRecordStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002786 process_notifyRecord(ctx, evt->record.event, &status);
Zhiqiang Han620b9252021-11-09 14:23:20 +08002787 wrapper_saveRecordStatistics(ctx->record.param_open.location, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002788 } break;
2789 default:
2790 break;
2791 }
2792 } break;
hualing chen4b7c15d2020-04-07 16:13:48 +08002793 case DVR_RECORD_EVENT_WRITE_ERROR: {
2794 ctx->record.seg_status = evt->record.status;
2795 status.state = evt->record.status.state;
2796 process_notifyRecord(ctx, evt->record.event, &status);
2797 }break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002798 default:
2799 break;
2800 }
2801 return DVR_SUCCESS;
2802}
2803
2804static inline int process_notifyPlayback(DVR_WrapperCtx_t *ctx, DVR_PlaybackEvent_t evt, DVR_WrapperPlaybackStatus_t *status)
2805{
Wentao MA96f68962022-06-15 19:45:35 +08002806 DVR_WRAPPER_INFO("notify(sn:%ld) evt(0x%x) statistics:state/cur/full/obsl(%d/%ld/%ld/%ld)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002807 ctx->sn,
2808 evt,
2809 status->state,
2810 status->info_cur.time,
2811 status->info_full.time,
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002812 status->info_obsolete.time);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002813
2814 if (ctx->playback.event_fn)
2815 return ctx->playback.event_fn(evt, status, ctx->playback.event_userdata);
2816 return 0;
2817}
2818
2819/*should run periodically to update the current status*/
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002820static int process_generatePlaybackStatus(DVR_WrapperCtx_t *ctx, DVR_WrapperPlaybackStatus_t *status)
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002821{
2822 /*the current seg is not covered in the statistics*/
2823 DVR_WrapperPlaybackSegmentInfo_t *pseg;
2824
2825 memset(&ctx->playback.status, 0, sizeof(ctx->playback.status));
2826 ctx->playback.status.pids = ctx->playback.pids_req;
2827
2828 ctx->playback.status.state = ctx->playback.seg_status.state;
2829 ctx->playback.status.speed = ctx->playback.seg_status.speed;
2830 ctx->playback.status.flags = ctx->playback.seg_status.flags;
2831 ctx->current_segment_id = ctx->playback.seg_status.segment_id;
2832
2833 list_for_each_entry_reverse(pseg, &ctx->segments, head) {
hualing chen451c8f72022-03-09 13:05:52 +08002834 if (pseg->seg_info.id == ctx->playback.seg_status.segment_id) {
Wentao MA96f68962022-06-15 19:45:35 +08002835 DVR_WRAPPER_INFO("caulate cur time :[%lld]time[%d]\n", pseg->seg_info.id, pseg->seg_info.duration);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002836 break;
hualing chen451c8f72022-03-09 13:05:52 +08002837 }
2838
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002839 ctx->playback.status.info_cur.time += pseg->seg_info.duration;
2840 ctx->playback.status.info_cur.size += pseg->seg_info.size;
2841 ctx->playback.status.info_cur.pkts += pseg->seg_info.nb_packets;
2842 }
2843 list_for_each_entry_reverse(pseg, &ctx->segments, head) {
2844 ctx->playback.status.info_full.time += pseg->seg_info.duration;
2845 ctx->playback.status.info_full.size += pseg->seg_info.size;
2846 ctx->playback.status.info_full.pkts += pseg->seg_info.nb_packets;
Wentao MA96f68962022-06-15 19:45:35 +08002847 DVR_WRAPPER_INFO("caulate full time :[%lld]time[%d]\n", pseg->seg_info.id, pseg->seg_info.duration);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002848 }
2849
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002850 if (status) {
2851 *status = ctx->playback.status;
2852 /*deal with current, lack size and pkts with the current*/
2853 status->info_cur.time += ctx->playback.seg_status.time_cur;
hualing chen56c0a162022-01-27 17:01:50 +08002854 //get last segment id
2855 DVR_WrapperRecordSegmentInfo_t *pseg;
2856
2857 pseg = list_last_entry(&ctx->segments, DVR_WrapperRecordSegmentInfo_t, head);
2858 if (ctx->playback.tf_full == DVR_TRUE && pseg->info.id == ctx->current_segment_id) {
2859 status->disguised_info_obsolete.time = ctx->playback.obsolete.time + ctx->playback.seg_status.time_cur;
2860 status->info_obsolete.time = ctx->playback.obsolete.time;
Wentao MA96f68962022-06-15 19:45:35 +08002861 DVR_WRAPPER_INFO("warning change start time :id[%lld] [%d]cur[%d]\n", pseg->info.id, status->info_obsolete.time, status->info_cur.time);
hualing chen56c0a162022-01-27 17:01:50 +08002862 }
2863 else
2864 {
Wentao MA96f68962022-06-15 19:45:35 +08002865 DVR_WRAPPER_INFO("warning not change start time :ctx->playback.tf_full[%d]id[%lld] [%lld] cur[%d]\n",ctx->playback.tf_full , pseg->info.id, ctx->current_segment_id, status->info_cur.time);
hualing chen56c0a162022-01-27 17:01:50 +08002866 status->info_obsolete.time = ctx->playback.obsolete.time;
2867 status->disguised_info_obsolete.time = ctx->playback.obsolete.time;
2868 }
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002869 }
2870
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002871 return DVR_SUCCESS;
2872}
2873
2874static int process_handlePlaybackEvent(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
2875{
Wentao MA96f68962022-06-15 19:45:35 +08002876 DVR_WRAPPER_INFO("evt (sn:%ld) 0x%x (state:%d) cur(%lld:%u/%u)\n",
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002877 evt->sn, evt->playback.event,
2878 evt->playback.status.play_status.state,
2879 evt->playback.status.play_status.segment_id,
2880 evt->playback.status.play_status.time_cur,
2881 evt->playback.status.play_status.time_end);
2882
2883 /*evt PLAYTIME will break the last logic, do not save*/
hualing chene3797f02021-01-13 14:53:28 +08002884 if (evt->playback.event != DVR_PLAYBACK_EVENT_NOTIFY_PLAYTIME
2885 && evt->playback.event != DVR_PLAYBACK_EVENT_NODATA
2886 && evt->playback.event != DVR_PLAYBACK_EVENT_DATARESUME
2887 )
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002888 ctx->playback.last_event = evt->playback.event;
2889
2890 switch (evt->playback.event)
2891 {
2892 case DVR_PLAYBACK_EVENT_FIRST_FRAME:
2893 case DVR_PLAYBACK_EVENT_REACHED_END:
2894 case DVR_PLAYBACK_EVENT_TRANSITION_OK:
2895 case DVR_PLAYBACK_EVENT_NOTIFY_PLAYTIME:
hualing chenb5cd42e2020-04-15 17:03:34 +08002896 case DVR_PLAYBACK_EVENT_ERROR:
hualing chenf291cf32020-06-18 10:50:30 +08002897 case DVR_PLAYBACK_EVENT_REACHED_BEGIN:
hualing chene3797f02021-01-13 14:53:28 +08002898 case DVR_PLAYBACK_EVENT_NODATA:
2899 case DVR_PLAYBACK_EVENT_DATARESUME:
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002900 {
2901 DVR_WrapperPlaybackStatus_t status;
2902
2903 /*copy status of segment*/
2904 ctx->playback.seg_status = evt->playback.status.play_status;
2905
Zhiqiang Hanaeb0c712020-04-30 15:17:26 +08002906 /*generate status of the whole playback*/
2907 process_generatePlaybackStatus(ctx, &status);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002908
2909 if (evt->playback.event == DVR_PLAYBACK_EVENT_REACHED_END) {
Wentao MA96f68962022-06-15 19:45:35 +08002910 DVR_WRAPPER_INFO("playback(sn:%ld) event:0x%x\n", evt->sn, evt->playback.event);
hualing chenb9b358a2021-08-17 15:06:36 +08002911 if (ctx->playback.param_open.is_timeshift
2912 || ctx_isPlay_recording(ctx->playback.param_open.location)) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002913 /*wait for more data in recording*/
Zhiqiang Han31846002021-11-04 10:49:06 +08002914 }
2915 /*trust the low level, make NO check.
2916 As this evt is changed to only once due to some operations(paused) in low level.
2917 else if ((status.info_cur.time + DVR_PLAYBACK_END_GAP) >= ctx->playback.status.info_full.time) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002918 process_notifyPlayback(ctx, evt->playback.event, &status);
Zhiqiang Han31846002021-11-04 10:49:06 +08002919 }
2920 */
2921 else {
2922 process_notifyPlayback(ctx, evt->playback.event, &status);
hualing chenb5cd42e2020-04-15 17:03:34 +08002923 ctx->playback.reach_end = DVR_TRUE;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002924 }
hualing chenf291cf32020-06-18 10:50:30 +08002925 } else if (evt->playback.event != DVR_PLAYBACK_EVENT_REACHED_BEGIN) {
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002926 process_notifyPlayback(ctx, evt->playback.event, &status);
2927 }
2928 } break;
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002929 case DVR_PLAYBACK_EVENT_TRANSITION_FAILED:
2930 case DVR_PLAYBACK_EVENT_KEY_FAILURE:
2931 case DVR_PLAYBACK_EVENT_NO_KEY:
2932 {
Wentao MA96f68962022-06-15 19:45:35 +08002933 DVR_WRAPPER_INFO("playback(sn:%ld) error event:0x%x\n", evt->sn, evt->playback.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002934 } break;
2935 default:
2936 {
Wentao MA96f68962022-06-15 19:45:35 +08002937 DVR_WRAPPER_INFO("playback(sn:%ld) unknown event:0x%x\n", evt->sn, evt->playback.event);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +08002938 } break;
2939 }
2940 return 0;
2941}
2942
2943static inline int process_handleEvents(DVR_WrapperEventCtx_t *evt, DVR_WrapperCtx_t *ctx)
2944{
2945 return (evt->type == W_REC)? process_handleRecordEvent(evt, ctx) : process_handlePlaybackEvent(evt, ctx);
2946}
2947
Wentao MA96f68962022-06-15 19:45:35 +08002948int dvr_wrapper_set_log_level (int level)
2949{
2950 if (level<LOG_LV_DEFAULT || level>LOG_LV_FATAL) {
2951 DVR_WRAPPER_ERROR("Invalid dvr log level:%d", g_dvr_log_level);
2952 return DVR_FAILURE;
2953 }
2954 g_dvr_log_level = level;
2955 DVR_WRAPPER_INFO("New dvr log level:%d", g_dvr_log_level);
2956 return DVR_SUCCESS;
2957}
2958