blob: a2a94fe879ac365ca998fe5ab626a80172029ce6 [file] [log] [blame]
Pengfei Liuc181a982020-01-07 19:27:13 +08001#include <stdio.h>
Pengfei Liub4734232020-01-17 18:25:10 +08002#include <unistd.h>
3#include <stdlib.h>
Pengfei Liuc181a982020-01-07 19:27:13 +08004#include <pthread.h>
Pengfei Liub4734232020-01-17 18:25:10 +08005#include <string.h>
Pengfei Liu47ed6c92020-01-17 11:23:41 +08006#include "dvr_types.h"
Pengfei Liuc181a982020-01-07 19:27:13 +08007#include "dvr_record.h"
8#include "dvr_crypto.h"
9#include "record_device.h"
10#include "segment.h"
Pengfei Liuc181a982020-01-07 19:27:13 +080011
12#define MAX_DVR_RECORD_SESSION_COUNT 2
pengfei.liuab5a2262020-02-14 17:33:40 +080013
14/**\brief DVR index file type*/
15typedef enum {
16 DVR_INDEX_TYPE_PCR, /**< DVR index file use pcr*/
17 DVR_INDEX_TYPE_LOCAL_CLOCK, /**< DVR index file use local clock*/
18 DVR_INDEX_TYPE_INVALID /**< DVR index file type invalid type*/
19} DVR_IndexType_t;
20
21/**\brief DVR VOD context*/
22typedef struct {
23 pthread_mutex_t mutex; /**< VOD mutex lock*/
24 pthread_cond_t cond; /**< VOD condition*/
25 void *buffer; /**< VOD buffer*/
26 uint32_t buf_len; /**< VOD buffer len*/
27} DVR_VodContext_t;
28
Pengfei Liub4734232020-01-17 18:25:10 +080029/**\brief DVR record context*/
Pengfei Liuc181a982020-01-07 19:27:13 +080030typedef struct {
Pengfei Liub4734232020-01-17 18:25:10 +080031 pthread_t thread; /**< DVR thread handle*/
32 Record_DeviceHandle_t dev_handle; /**< DVR device handle*/
33 Segment_Handle_t segment_handle; /**< DVR segment handle*/
34 DVR_RecordState_t state; /**< DVR record state*/
35 char location[DVR_MAX_LOCATION_SIZE]; /**< DVR record file location*/
36 DVR_RecordSegmentStartParams_t segment_params; /**< DVR record start parameters*/
37 DVR_RecordSegmentInfo_t segment_info; /**< DVR record current segment info*/
38 size_t notification_size; /**< DVR record nogification size*/
39 DVR_RecordEventFunction_t event_notify_fn; /**< DVR record event notify function*/
40 void *event_userdata; /**< DVR record event userdata*/
pengfei.liuab5a2262020-02-14 17:33:40 +080041 //DVR_VodContext_t vod; /**< DVR record vod context*/
42 int is_vod; /**< Indicate current mode is VOD record mode*/
Pengfei Liuc181a982020-01-07 19:27:13 +080043} DVR_RecordContext_t;
44
45static DVR_RecordContext_t record_ctx[MAX_DVR_RECORD_SESSION_COUNT] = {
46 {
Pengfei Liub4734232020-01-17 18:25:10 +080047 .state = DVR_RECORD_STATE_CLOSED
Pengfei Liuc181a982020-01-07 19:27:13 +080048 },
49 {
Pengfei Liub4734232020-01-17 18:25:10 +080050 .state = DVR_RECORD_STATE_CLOSED
Pengfei Liuc181a982020-01-07 19:27:13 +080051 }
52};
53
pengfei.liuab5a2262020-02-14 17:33:40 +080054//#define USE_TEST_DATA
55#ifdef USE_TEST_DATA
56static int test_data_read(uint8_t *buf, int len)
57{
58 int i;
59 for (i = 0; i < len; i++) {
60 buf[i] = i % 0xff;
61 }
62 usleep(50*1000);
63 return len;
64}
65#endif
66
67static int record_save_pcr(DVR_RecordContext_t *p_ctx, uint8_t *buf, loff_t pos)
68{
69 uint8_t *p = buf;
70 int len;
71 uint8_t afc;
72 uint64_t pcr = 0;
73 int has_pcr = 0;
74 int pid;
75 int adp_field_len;
76
77 pid = ((p[1] & 0x1f) << 8) | p[2];
78 if (pid == 0x1fff)
79 return has_pcr;
80
81 //scramble = p[3] >> 6;
82 //cc = p[3] & 0x0f;
83 afc = (p[3] >> 4) & 0x03;
84
85 p += 4;
86 len = 184;
87
88 if (afc & 2) {
89 adp_field_len = p[0];
90 /* Skip adaptation len */
91 p++;
92 len--;
93 /* Parse pcr field, see 13818 spec table I-2-6,adaptation_field */
94 if (p[0] & 0x10 && len >= 6) {
95 /* get pcr value,pcr is 33bit value */
96 pcr = (((uint64_t)(p[1])) << 25)
97 | (((uint64_t)p[2]) << 17)
98 | (((uint64_t)(p[3])) << 9)
99 | (((uint64_t)p[4]) << 1)
100 | ((((uint64_t)p[5]) & 0x80) >> 7);
101 has_pcr = 1;
102 }
103
104 p += adp_field_len;
105 len -= adp_field_len;
106
107 if (len < 0) {
108 DVR_DEBUG(1, "parser pcr: illegal adaptation field length");
109 return 0;
110 }
111 }
112
113 if (has_pcr) {
114 segment_update_pts(p_ctx->segment_handle, pcr/90, pos);
115 }
116 return has_pcr;
117}
118
119static int record_do_pcr_index(DVR_RecordContext_t *p_ctx, uint8_t *buf, int len)
120{
121 uint8_t *p = buf;
122 int left = len;
123 loff_t pos;
124 int has_pcr = 0;
125
126 pos = segment_tell_position(p_ctx->segment_handle);
127 while (left >= 188) {
128 if (*p == 0x47) {
129 has_pcr |= record_save_pcr(p_ctx, p, pos);
130 p += 188;
131 left -= 188;
132 pos += 188;
133 } else {
134 p++;
135 left --;
136 pos++;
137 }
138 }
139 return has_pcr;
140}
141
Pengfei Liuc181a982020-01-07 19:27:13 +0800142void *record_thread(void *arg)
143{
144 DVR_RecordContext_t *p_ctx = (DVR_RecordContext_t *)arg;
145 ssize_t len;
146 uint8_t *buf;
Pengfei Liub4734232020-01-17 18:25:10 +0800147 int block_size = 256*1024;
pengfei.liuab5a2262020-02-14 17:33:40 +0800148 loff_t pos = 0;
Pengfei Liuc181a982020-01-07 19:27:13 +0800149 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800150 struct timespec start_ts, end_ts;
151 DVR_RecordStatus_t record_status;
pengfei.liuab5a2262020-02-14 17:33:40 +0800152 int has_pcr;
153 int index_type = DVR_INDEX_TYPE_INVALID;
hualing chen87072a82020-03-12 16:20:12 +0800154 time_t pre_time = 0;
155 #define DVR_STORE_INFO_TIME (1000)
Pengfei Liuc181a982020-01-07 19:27:13 +0800156
Pengfei Liub4734232020-01-17 18:25:10 +0800157 buf = (uint8_t *)malloc(block_size);
Pengfei Liuc181a982020-01-07 19:27:13 +0800158 if (!buf) {
159 DVR_DEBUG(1, "%s, malloc failed", __func__);
160 return NULL;
161 }
162
Pengfei Liub4734232020-01-17 18:25:10 +0800163 clock_gettime(CLOCK_MONOTONIC, &start_ts);
Pengfei Liuc181a982020-01-07 19:27:13 +0800164 while (p_ctx->state == DVR_RECORD_STATE_STARTED) {
pengfei.liuab5a2262020-02-14 17:33:40 +0800165 /* data from dmx, normal dvr case */
166#ifdef USE_TEST_DATA
167 len = test_data_read(buf, block_size);
168#else
Pengfei Liub4734232020-01-17 18:25:10 +0800169 len = record_device_read(p_ctx->dev_handle, buf, block_size, 1000);
pengfei.liuab5a2262020-02-14 17:33:40 +0800170#endif
Pengfei Liub4734232020-01-17 18:25:10 +0800171 if (len == DVR_FAILURE) {
172 usleep(10*1000);
173 continue;
174 }
pengfei.liuab5a2262020-02-14 17:33:40 +0800175 /* got data from device, record it */
176 pos = segment_tell_position(p_ctx->segment_handle);
177 has_pcr = record_do_pcr_index(p_ctx, buf, len);
178 if (has_pcr == 0 && index_type == DVR_INDEX_TYPE_INVALID) {
179 clock_gettime(CLOCK_MONOTONIC, &end_ts);
180 if ((end_ts.tv_sec*1000 + end_ts.tv_nsec/1000000) -
181 (start_ts.tv_sec*1000 + start_ts.tv_nsec/1000000) > 40) {
182 /* PCR interval threshlod > 40 ms*/
183 DVR_DEBUG(1, "%s use local clock time index", __func__);
184 index_type = DVR_INDEX_TYPE_LOCAL_CLOCK;
185 }
186 } else if (has_pcr && index_type == DVR_INDEX_TYPE_INVALID){
187 DVR_DEBUG(1, "%s use pcr time index", __func__);
188 index_type = DVR_INDEX_TYPE_PCR;
Pengfei Liuc181a982020-01-07 19:27:13 +0800189 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800190 ret = segment_write(p_ctx->segment_handle, buf, len);
pengfei.liuab5a2262020-02-14 17:33:40 +0800191
192 /* Update segment info */
Pengfei Liub4734232020-01-17 18:25:10 +0800193 p_ctx->segment_info.size += len;
pengfei.liuab5a2262020-02-14 17:33:40 +0800194 /*Duration need use pcr to calculate, todo...*/
195 if (index_type == DVR_INDEX_TYPE_PCR) {
pengfei.liu8b563292020-02-26 15:49:02 +0800196 p_ctx->segment_info.duration = segment_tell_total_time(p_ctx->segment_handle);
hualing chen87072a82020-03-12 16:20:12 +0800197 if (pre_time == 0)
198 pre_time = p_ctx->segment_info.duration;
pengfei.liuab5a2262020-02-14 17:33:40 +0800199 } else if (index_type == DVR_INDEX_TYPE_LOCAL_CLOCK) {
200 clock_gettime(CLOCK_MONOTONIC, &end_ts);
201 p_ctx->segment_info.duration = (end_ts.tv_sec*1000 + end_ts.tv_nsec/1000000) -
202 (start_ts.tv_sec*1000 + start_ts.tv_nsec/1000000);
hualing chen87072a82020-03-12 16:20:12 +0800203 if (pre_time == 0)
204 pre_time = p_ctx->segment_info.duration;
pengfei.liuab5a2262020-02-14 17:33:40 +0800205 segment_update_pts(p_ctx->segment_handle, p_ctx->segment_info.duration, pos);
206 } else {
207 DVR_DEBUG(1, "%s can NOT do time index", __func__);
208 }
209 p_ctx->segment_info.nb_packets = p_ctx->segment_info.size/188;
Pengfei Liub4734232020-01-17 18:25:10 +0800210
hualing chen87072a82020-03-12 16:20:12 +0800211 if (p_ctx->segment_info.duration - pre_time > DVR_STORE_INFO_TIME) {
212 pre_time = p_ctx->segment_info.duration + DVR_STORE_INFO_TIME;
213 segment_store_info(p_ctx->segment_handle, &(p_ctx->segment_info));
214 }
215 /*Event notification*/
Pengfei Liub4734232020-01-17 18:25:10 +0800216 if (p_ctx->notification_size &&
217 p_ctx->event_notify_fn &&
pengfei.liuab5a2262020-02-14 17:33:40 +0800218 !(p_ctx->segment_info.size % p_ctx->notification_size) &&
219 p_ctx->segment_info.duration > 0) {
Pengfei Liub4734232020-01-17 18:25:10 +0800220 memset(&record_status, 0, sizeof(record_status));
pengfei.liuab5a2262020-02-14 17:33:40 +0800221 //clock_gettime(CLOCK_MONOTONIC, &end_ts);
Pengfei Liub4734232020-01-17 18:25:10 +0800222
223 record_status.state = p_ctx->state;
224 record_status.info.id = p_ctx->segment_info.id;
pengfei.liuab5a2262020-02-14 17:33:40 +0800225 record_status.info.duration = p_ctx->segment_info.duration;
Pengfei Liub4734232020-01-17 18:25:10 +0800226 record_status.info.size = p_ctx->segment_info.size;
227 record_status.info.nb_packets = p_ctx->segment_info.size/188;
228 p_ctx->event_notify_fn(DVR_RECORD_EVENT_STATUS, &record_status, p_ctx->event_userdata);
229 DVR_DEBUG(1, "%s notify record status, state:%d, id:%lld, duration:%ld ms, size:%zu",
230 __func__, record_status.state, record_status.info.id, record_status.info.duration, record_status.info.size);
231 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800232 }
233
Pengfei Liub4734232020-01-17 18:25:10 +0800234 free((void *)buf);
235 DVR_DEBUG(1, "exit %s", __func__);
Pengfei Liuc181a982020-01-07 19:27:13 +0800236 return NULL;
237}
238
239int dvr_record_open(DVR_RecordHandle_t *p_handle, DVR_RecordOpenParams_t *params)
240{
241 DVR_RecordContext_t *p_ctx;
242 Record_DeviceOpenParams_t dev_open_params;
243 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800244 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800245
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800246 DVR_RETURN_IF_FALSE(p_handle);
247 DVR_RETURN_IF_FALSE(params);
Pengfei Liuc181a982020-01-07 19:27:13 +0800248
249 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
Pengfei Liub4734232020-01-17 18:25:10 +0800250 if (record_ctx[i].state == DVR_RECORD_STATE_CLOSED) {
Pengfei Liuc181a982020-01-07 19:27:13 +0800251 break;
252 }
253 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800254 DVR_RETURN_IF_FALSE(record_ctx[i].state == DVR_RECORD_STATE_CLOSED);
Pengfei Liuc181a982020-01-07 19:27:13 +0800255 p_ctx = &record_ctx[i];
Pengfei Liub4734232020-01-17 18:25:10 +0800256 DVR_DEBUG(1, "%s , current state:%d, dmx_id:%d, notification_size:%zu", __func__,
257 p_ctx->state, params->dmx_dev_id, params->notification_size);
Pengfei Liuc181a982020-01-07 19:27:13 +0800258
Pengfei Liub4734232020-01-17 18:25:10 +0800259 /*Process event params*/
260 p_ctx->notification_size = params->notification_size;
261 p_ctx->event_notify_fn = params->event_fn;
262 p_ctx->event_userdata = params->event_userdata;
263 /*Process crypto params, todo*/
264#if 0
265 DVR_CryptoPeriod_t crypto_period; /**< DVR crypto period information*/
266 DVR_CryptoFunction_t crypto_fn; /**< DVR crypto callback function*/
267 void *crypto_data; /**< DVR crypto userdata*/
268#endif
Pengfei Liuc181a982020-01-07 19:27:13 +0800269
Pengfei Liub4734232020-01-17 18:25:10 +0800270 memset((void *)&dev_open_params, 0, sizeof(dev_open_params));
pengfei.liuab5a2262020-02-14 17:33:40 +0800271 if (params->data_from_memory) {
272 /* data from memory, VOD case */
273 p_ctx->is_vod = 1;
274 } else {
275 p_ctx->is_vod = 0;
276 /* data from dmx, normal dvr case */
hualing chen958fe4c2020-03-24 17:35:07 +0800277 dev_open_params.dmx_dev_id = params->dmx_dev_id;
pengfei.liuab5a2262020-02-14 17:33:40 +0800278 dev_open_params.buf_size = 256*1024;
Pengfei Liub4734232020-01-17 18:25:10 +0800279
pengfei.liuab5a2262020-02-14 17:33:40 +0800280 ret = record_device_open(&p_ctx->dev_handle, &dev_open_params);
281 if (ret != DVR_SUCCESS) {
282 DVR_DEBUG(1, "%s, open record devices failed", __func__);
283 return DVR_FAILURE;
284 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800285 }
286
287 p_ctx->state = DVR_RECORD_STATE_OPENED;
288
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800289 *p_handle = p_ctx;
Pengfei Liuc181a982020-01-07 19:27:13 +0800290 return DVR_SUCCESS;
291}
292
293int dvr_record_close(DVR_RecordHandle_t handle)
294{
295 DVR_RecordContext_t *p_ctx;
296 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800297 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800298
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800299 p_ctx = (DVR_RecordContext_t *)handle;
300 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
301 if (p_ctx == &record_ctx[i])
302 break;
303 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800304 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800305
Pengfei Liub4734232020-01-17 18:25:10 +0800306 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800307 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
Pengfei Liuc181a982020-01-07 19:27:13 +0800308
pengfei.liuab5a2262020-02-14 17:33:40 +0800309 if (p_ctx->is_vod) {
310 ret = DVR_SUCCESS;
311 } else {
312 ret = record_device_close(p_ctx->dev_handle);
313 if (ret != DVR_SUCCESS) {
314 DVR_DEBUG(1, "%s, failed", __func__);
315 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800316 }
317
Pengfei Liub4734232020-01-17 18:25:10 +0800318 p_ctx->state = DVR_RECORD_STATE_CLOSED;
Pengfei Liuc181a982020-01-07 19:27:13 +0800319 return ret;
320}
321
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800322#if 0
Pengfei Liuc181a982020-01-07 19:27:13 +0800323int dvr_record_register_encryption(DVR_RecordHandle_t handle,
324 DVR_CryptoFunction_t cb,
325 DVR_CryptoParams_t params,
326 void *userdata)
327{
328 return DVR_SUCCESS;
329}
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800330#endif
Pengfei Liuc181a982020-01-07 19:27:13 +0800331
332int dvr_record_start_segment(DVR_RecordHandle_t handle, DVR_RecordStartParams_t *params)
333{
334 DVR_RecordContext_t *p_ctx;
335 Segment_OpenParams_t open_params;
336 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800337 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800338
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800339 p_ctx = (DVR_RecordContext_t *)handle;
340 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
341 if (p_ctx == &record_ctx[i])
342 break;
343 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800344 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800345
Pengfei Liub4734232020-01-17 18:25:10 +0800346 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800347 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_STARTED);
348 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
349 DVR_RETURN_IF_FALSE(params);
Pengfei Liuc181a982020-01-07 19:27:13 +0800350
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800351 DVR_RETURN_IF_FALSE(strlen((const char *)params->location) < DVR_MAX_LOCATION_SIZE);
Pengfei Liuc181a982020-01-07 19:27:13 +0800352 memset(&open_params, 0, sizeof(open_params));
353 memcpy(open_params.location, params->location, strlen(params->location));
354 open_params.segment_id = params->segment.segment_id;
355 open_params.mode = SEGMENT_MODE_WRITE;
356
357 ret = segment_open(&open_params, &p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800358 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800359
Pengfei Liub4734232020-01-17 18:25:10 +0800360 /*process params*/
Pengfei Liuc181a982020-01-07 19:27:13 +0800361 {
362 memcpy(p_ctx->location, params->location, strlen(params->location));
Pengfei Liub4734232020-01-17 18:25:10 +0800363 //need all params??
Pengfei Liuc181a982020-01-07 19:27:13 +0800364 memcpy(&p_ctx->segment_params, &params->segment, sizeof(params->segment));
Pengfei Liub4734232020-01-17 18:25:10 +0800365 /*save current segment info*/
366 memset(&p_ctx->segment_info, 0, sizeof(p_ctx->segment_info));
367 p_ctx->segment_info.id = params->segment.segment_id;
368 p_ctx->segment_info.nb_pids = params->segment.nb_pids;
369 memcpy(p_ctx->segment_info.pids, params->segment.pids, params->segment.nb_pids*sizeof(DVR_StreamPid_t));
Pengfei Liuc181a982020-01-07 19:27:13 +0800370 }
371
pengfei.liuab5a2262020-02-14 17:33:40 +0800372 if (!p_ctx->is_vod) {
373 /* normal dvr case */
374 for (i = 0; i < params->segment.nb_pids; i++) {
375 ret = record_device_add_pid(p_ctx->dev_handle, params->segment.pids[i].pid);
376 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
377 }
378 ret = record_device_start(p_ctx->dev_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800379 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800380 }
381
Pengfei Liuc181a982020-01-07 19:27:13 +0800382 p_ctx->state = DVR_RECORD_STATE_STARTED;
pengfei.liuab5a2262020-02-14 17:33:40 +0800383 if (!p_ctx->is_vod)
384 pthread_create(&p_ctx->thread, NULL, record_thread, p_ctx);
Pengfei Liub4734232020-01-17 18:25:10 +0800385
Pengfei Liuc181a982020-01-07 19:27:13 +0800386 return DVR_SUCCESS;
387}
388
389int dvr_record_next_segment(DVR_RecordHandle_t handle, DVR_RecordStartParams_t *params, DVR_RecordSegmentInfo_t *p_info)
390{
391 DVR_RecordContext_t *p_ctx;
Pengfei Liub4734232020-01-17 18:25:10 +0800392 Segment_OpenParams_t open_params;
Pengfei Liuc181a982020-01-07 19:27:13 +0800393 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800394 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800395
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800396 p_ctx = (DVR_RecordContext_t *)handle;
397 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
398 if (p_ctx == &record_ctx[i])
399 break;
400 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800401 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800402
Pengfei Liub4734232020-01-17 18:25:10 +0800403 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800404 DVR_RETURN_IF_FALSE(p_ctx->state == DVR_RECORD_STATE_STARTED);
405 //DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
406 DVR_RETURN_IF_FALSE(params);
407 DVR_RETURN_IF_FALSE(p_info);
pengfei.liuab5a2262020-02-14 17:33:40 +0800408 DVR_RETURN_IF_FALSE(!p_ctx->is_vod);
Pengfei Liuc181a982020-01-07 19:27:13 +0800409
410 /*Stop the on going record segment*/
Pengfei Liub4734232020-01-17 18:25:10 +0800411 //ret = record_device_stop(p_ctx->dev_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800412 //DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800413
414 p_ctx->state = DVR_RECORD_STATE_STOPPED;
415 pthread_join(p_ctx->thread, NULL);
416
Pengfei Liub4734232020-01-17 18:25:10 +0800417 /*Update segment info*/
418 memcpy(p_info, &p_ctx->segment_info, sizeof(p_ctx->segment_info));
419
420 ret = segment_store_info(p_ctx->segment_handle, p_info);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800421 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800422
hualing chena540a7e2020-03-27 16:44:05 +0800423 DVR_DEBUG(1, "%s dump segment info, id:%lld, nb_pids:%d, duration:%ld ms, size:%zu, nb_packets:%d params->segment.nb_pids:%d",
424 __func__, p_info->id, p_info->nb_pids, p_info->duration, p_info->size, p_info->nb_packets, params->segment.nb_pids);
Pengfei Liuc181a982020-01-07 19:27:13 +0800425
Pengfei Liub4734232020-01-17 18:25:10 +0800426 /*Close current segment*/
427 ret = segment_close(p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800428 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800429 /*Open the new record segment*/
430 memset(&open_params, 0, sizeof(open_params));
431 memcpy(open_params.location, p_ctx->location, strlen(p_ctx->location));
432 open_params.segment_id = params->segment.segment_id;
433 open_params.mode = SEGMENT_MODE_WRITE;
434
435 ret = segment_open(&open_params, &p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800436 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800437 /*process params*/
Pengfei Liuc181a982020-01-07 19:27:13 +0800438 {
Pengfei Liub4734232020-01-17 18:25:10 +0800439 //need all params??
Pengfei Liuc181a982020-01-07 19:27:13 +0800440 memcpy(&p_ctx->segment_params, &params->segment, sizeof(params->segment));
Pengfei Liub4734232020-01-17 18:25:10 +0800441 /*save current segment info*/
442 memset(&p_ctx->segment_info, 0, sizeof(p_ctx->segment_info));
443 p_ctx->segment_info.id = params->segment.segment_id;
444 memcpy(p_ctx->segment_info.pids, params->segment.pids, params->segment.nb_pids*sizeof(DVR_StreamPid_t));
Pengfei Liuc181a982020-01-07 19:27:13 +0800445 }
446
Pengfei Liub4734232020-01-17 18:25:10 +0800447 p_ctx->segment_info.nb_pids = 0;
Pengfei Liuc181a982020-01-07 19:27:13 +0800448 for (i = 0; i < params->segment.nb_pids; i++) {
Pengfei Liub4734232020-01-17 18:25:10 +0800449 switch (params->segment.pid_action[i]) {
450 case DVR_RECORD_PID_CREATE:
451 DVR_DEBUG(1, "%s create pid:%d", __func__, params->segment.pids[i].pid);
452 ret = record_device_add_pid(p_ctx->dev_handle, params->segment.pids[i].pid);
453 p_ctx->segment_info.nb_pids++;
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800454 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800455 break;
456 case DVR_RECORD_PID_KEEP:
457 DVR_DEBUG(1, "%s keep pid:%d", __func__, params->segment.pids[i].pid);
458 p_ctx->segment_info.nb_pids++;
459 break;
460 case DVR_RECORD_PID_CLOSE:
461 DVR_DEBUG(1, "%s close pid:%d", __func__, params->segment.pids[i].pid);
462 ret = record_device_remove_pid(p_ctx->dev_handle, params->segment.pids[i].pid);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800463 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800464 break;
465 default:
466 DVR_DEBUG(1, "%s wrong action pid:%d", __func__, params->segment.pids[i].pid);
467 return DVR_FAILURE;
468 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800469 }
470
Pengfei Liub4734232020-01-17 18:25:10 +0800471 //ret = record_device_start(p_ctx->dev_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800472 //DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800473
474 pthread_create(&p_ctx->thread, NULL, record_thread, p_ctx);
475 p_ctx->state = DVR_RECORD_STATE_STARTED;
476 return DVR_SUCCESS;
477}
478
479int dvr_record_stop_segment(DVR_RecordHandle_t handle, DVR_RecordSegmentInfo_t *p_info)
480{
481 DVR_RecordContext_t *p_ctx;
482 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800483 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800484
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800485 p_ctx = (DVR_RecordContext_t *)handle;
486 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
487 if (p_ctx == &record_ctx[i])
488 break;
489 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800490 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800491
Pengfei Liub4734232020-01-17 18:25:10 +0800492 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800493 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_STOPPED);
494 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
495 DVR_RETURN_IF_FALSE(p_info);
Pengfei Liuc181a982020-01-07 19:27:13 +0800496
Pengfei Liuc181a982020-01-07 19:27:13 +0800497 p_ctx->state = DVR_RECORD_STATE_STOPPED;
pengfei.liuab5a2262020-02-14 17:33:40 +0800498 if (p_ctx->is_vod) {
pengfei.liu8b563292020-02-26 15:49:02 +0800499 p_ctx->segment_info.duration = segment_tell_total_time(p_ctx->segment_handle);
pengfei.liuab5a2262020-02-14 17:33:40 +0800500 p_ctx->segment_info.duration = 10*1000; //debug, should delete it
501 } else {
502 ret = record_device_stop(p_ctx->dev_handle);
503 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
504 //p_ctx->state = DVR_RECORD_STATE_STOPPED;
505 pthread_join(p_ctx->thread, NULL);
506 }
507
Pengfei Liuc181a982020-01-07 19:27:13 +0800508
Pengfei Liub4734232020-01-17 18:25:10 +0800509 /*Update segment info*/
510 memcpy(p_info, &p_ctx->segment_info, sizeof(p_ctx->segment_info));
511
512 ret = segment_store_info(p_ctx->segment_handle, p_info);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800513 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800514
515 DVR_DEBUG(1, "%s dump segment info, id:%lld, nb_pids:%d, duration:%ld ms, size:%zu, nb_packets:%d",
516 __func__, p_info->id, p_info->nb_pids, p_info->duration, p_info->size, p_info->nb_packets);
517
Pengfei Liuc181a982020-01-07 19:27:13 +0800518 ret = segment_close(p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800519 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800520 return DVR_SUCCESS;
521}
Pengfei Liuc181a982020-01-07 19:27:13 +0800522
Pengfei Liub4734232020-01-17 18:25:10 +0800523int dvr_record_resume_segment(DVR_RecordHandle_t handle, DVR_RecordStartParams_t *params, uint64_t *p_resume_size)
524{
525 DVR_RecordContext_t *p_ctx;
526 uint32_t i;
pengfei.liuab5a2262020-02-14 17:33:40 +0800527 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800528
529 p_ctx = (DVR_RecordContext_t *)handle;
530 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
531 if (p_ctx == &record_ctx[i])
532 break;
Pengfei Liuc181a982020-01-07 19:27:13 +0800533 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800534 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
535 DVR_RETURN_IF_FALSE(params);
536 DVR_RETURN_IF_FALSE(p_resume_size);
Pengfei Liuc181a982020-01-07 19:27:13 +0800537
pengfei.liuab5a2262020-02-14 17:33:40 +0800538 DVR_DEBUG(1, "%s , current state:%d, resume size:%lld", __func__, p_ctx->state, *p_resume_size);
539 ret = dvr_record_start_segment(handle, params);
540 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
541
542 p_ctx->segment_info.size = *p_resume_size;
543
544 return DVR_SUCCESS;
545}
546
547int dvr_record_get_status(DVR_RecordHandle_t handle, DVR_RecordStatus_t *p_status)
548{
549 DVR_RecordContext_t *p_ctx;
550 int i;
551
552 p_ctx = (DVR_RecordContext_t *)handle;
553 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
554 if (p_ctx == &record_ctx[i])
555 break;
556 }
557 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
558 DVR_RETURN_IF_FALSE(p_status);
559
560 //lock
561 p_status->state = p_ctx->state;
562 p_status->info.id = p_ctx->segment_info.id;
563 p_status->info.duration = p_ctx->segment_info.duration;
564 p_status->info.size = p_ctx->segment_info.size;
565 p_status->info.nb_packets = p_ctx->segment_info.size/188;
566
567 return DVR_SUCCESS;
568}
569
570int dvr_record_write(DVR_RecordHandle_t handle, void *buffer, uint32_t len)
571{
572 DVR_RecordContext_t *p_ctx;
573 uint32_t i;
574 off_t pos = 0;
575 int ret;
576 int has_pcr;
577
578 p_ctx = (DVR_RecordContext_t *)handle;
579 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
580 if (p_ctx == &record_ctx[i])
581 break;
582 }
583 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
584 DVR_RETURN_IF_FALSE(buffer);
585 DVR_RETURN_IF_FALSE(len);
586
587 pos = segment_tell_position(p_ctx->segment_handle);
588 has_pcr = record_do_pcr_index(p_ctx, buffer, len);
589 if (has_pcr == 0) {
590 /* Pull VOD record shoud use PCR time index */
591 DVR_DEBUG(1, "%s has no pcr, can NOT do time index", __func__);
592 }
593 ret = segment_write(p_ctx->segment_handle, buffer, len);
594 p_ctx->segment_info.size += len;
595 p_ctx->segment_info.nb_packets = p_ctx->segment_info.size/188;
596
Pengfei Liuc181a982020-01-07 19:27:13 +0800597 return DVR_SUCCESS;
598}