blob: 14ad8a25c9684664414584aa058505ccea2e748e [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
hualing chen266b9502020-04-04 17:39:39 +080013//#define RECORD_BLOCK_SIZE (64 * 1024)
14#define RECORD_BLOCK_SIZE (256 * 1024)
pengfei.liuab5a2262020-02-14 17:33:40 +080015
16/**\brief DVR index file type*/
17typedef enum {
18 DVR_INDEX_TYPE_PCR, /**< DVR index file use pcr*/
19 DVR_INDEX_TYPE_LOCAL_CLOCK, /**< DVR index file use local clock*/
20 DVR_INDEX_TYPE_INVALID /**< DVR index file type invalid type*/
21} DVR_IndexType_t;
22
23/**\brief DVR VOD context*/
24typedef struct {
25 pthread_mutex_t mutex; /**< VOD mutex lock*/
26 pthread_cond_t cond; /**< VOD condition*/
27 void *buffer; /**< VOD buffer*/
28 uint32_t buf_len; /**< VOD buffer len*/
29} DVR_VodContext_t;
30
pengfei.liu07ddc8a2020-03-24 23:36:53 +080031/**\brief DVR record secure mode buffer*/
32typedef struct {
33 uint32_t addr; /**< Secure mode record buffer address*/
34 uint32_t len; /**< Secure mode record buffer length*/
35} DVR_SecureBuffer_t;
36
Pengfei Liub4734232020-01-17 18:25:10 +080037/**\brief DVR record context*/
Pengfei Liuc181a982020-01-07 19:27:13 +080038typedef struct {
Pengfei Liub4734232020-01-17 18:25:10 +080039 pthread_t thread; /**< DVR thread handle*/
40 Record_DeviceHandle_t dev_handle; /**< DVR device handle*/
41 Segment_Handle_t segment_handle; /**< DVR segment handle*/
42 DVR_RecordState_t state; /**< DVR record state*/
43 char location[DVR_MAX_LOCATION_SIZE]; /**< DVR record file location*/
44 DVR_RecordSegmentStartParams_t segment_params; /**< DVR record start parameters*/
45 DVR_RecordSegmentInfo_t segment_info; /**< DVR record current segment info*/
46 size_t notification_size; /**< DVR record nogification size*/
47 DVR_RecordEventFunction_t event_notify_fn; /**< DVR record event notify function*/
48 void *event_userdata; /**< DVR record event userdata*/
pengfei.liuab5a2262020-02-14 17:33:40 +080049 //DVR_VodContext_t vod; /**< DVR record vod context*/
50 int is_vod; /**< Indicate current mode is VOD record mode*/
pengfei.liu27cc4ec2020-04-03 16:28:16 +080051 DVR_CryptoFunction_t enc_func; /**< Encrypt function*/
pengfei.liu07ddc8a2020-03-24 23:36:53 +080052 void *enc_userdata; /**< Encrypt userdata*/
53 int is_secure_mode; /**< Record session run in secure pipeline */
hualing chen2615aa82020-04-02 21:32:51 +080054 size_t last_send_size; /**< Last send notify segment size */
Pengfei Liuc181a982020-01-07 19:27:13 +080055} DVR_RecordContext_t;
56
57static DVR_RecordContext_t record_ctx[MAX_DVR_RECORD_SESSION_COUNT] = {
58 {
Pengfei Liub4734232020-01-17 18:25:10 +080059 .state = DVR_RECORD_STATE_CLOSED
Pengfei Liuc181a982020-01-07 19:27:13 +080060 },
61 {
Pengfei Liub4734232020-01-17 18:25:10 +080062 .state = DVR_RECORD_STATE_CLOSED
Pengfei Liuc181a982020-01-07 19:27:13 +080063 }
64};
65
Zhiqiang Han51646a02020-04-05 18:43:22 +080066static int record_is_valid_pid(DVR_RecordContext_t *p_ctx, int pid)
67{
68 int i;
69
70 for (i = 0; i < p_ctx->segment_info.nb_pids; i++) {
71 if (pid == p_ctx->segment_info.pids[i].pid)
72 return 1;
73 }
74 return 0;
75}
76
pengfei.liuab5a2262020-02-14 17:33:40 +080077static int record_save_pcr(DVR_RecordContext_t *p_ctx, uint8_t *buf, loff_t pos)
78{
79 uint8_t *p = buf;
80 int len;
81 uint8_t afc;
82 uint64_t pcr = 0;
83 int has_pcr = 0;
84 int pid;
85 int adp_field_len;
86
87 pid = ((p[1] & 0x1f) << 8) | p[2];
Zhiqiang Han51646a02020-04-05 18:43:22 +080088 if (pid == 0x1fff || !record_is_valid_pid(p_ctx, pid))
pengfei.liuab5a2262020-02-14 17:33:40 +080089 return has_pcr;
90
91 //scramble = p[3] >> 6;
92 //cc = p[3] & 0x0f;
93 afc = (p[3] >> 4) & 0x03;
94
95 p += 4;
96 len = 184;
97
98 if (afc & 2) {
99 adp_field_len = p[0];
100 /* Skip adaptation len */
101 p++;
102 len--;
103 /* Parse pcr field, see 13818 spec table I-2-6,adaptation_field */
104 if (p[0] & 0x10 && len >= 6) {
105 /* get pcr value,pcr is 33bit value */
106 pcr = (((uint64_t)(p[1])) << 25)
107 | (((uint64_t)p[2]) << 17)
108 | (((uint64_t)(p[3])) << 9)
109 | (((uint64_t)p[4]) << 1)
110 | ((((uint64_t)p[5]) & 0x80) >> 7);
111 has_pcr = 1;
112 }
113
114 p += adp_field_len;
115 len -= adp_field_len;
116
117 if (len < 0) {
118 DVR_DEBUG(1, "parser pcr: illegal adaptation field length");
119 return 0;
120 }
121 }
122
123 if (has_pcr) {
124 segment_update_pts(p_ctx->segment_handle, pcr/90, pos);
125 }
126 return has_pcr;
127}
128
129static int record_do_pcr_index(DVR_RecordContext_t *p_ctx, uint8_t *buf, int len)
130{
131 uint8_t *p = buf;
132 int left = len;
133 loff_t pos;
134 int has_pcr = 0;
135
136 pos = segment_tell_position(p_ctx->segment_handle);
137 while (left >= 188) {
138 if (*p == 0x47) {
139 has_pcr |= record_save_pcr(p_ctx, p, pos);
140 p += 188;
141 left -= 188;
142 pos += 188;
143 } else {
144 p++;
145 left --;
146 pos++;
147 }
148 }
149 return has_pcr;
150}
151
Pengfei Liuc181a982020-01-07 19:27:13 +0800152void *record_thread(void *arg)
153{
154 DVR_RecordContext_t *p_ctx = (DVR_RecordContext_t *)arg;
155 ssize_t len;
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800156 uint8_t *buf, *buf_out;
157 int block_size = RECORD_BLOCK_SIZE;//256*1024;
pengfei.liuab5a2262020-02-14 17:33:40 +0800158 loff_t pos = 0;
Pengfei Liuc181a982020-01-07 19:27:13 +0800159 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800160 struct timespec start_ts, end_ts;
161 DVR_RecordStatus_t record_status;
pengfei.liuab5a2262020-02-14 17:33:40 +0800162 int has_pcr;
163 int index_type = DVR_INDEX_TYPE_INVALID;
hualing chen87072a82020-03-12 16:20:12 +0800164 time_t pre_time = 0;
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800165 uint32_t out_len;
hualing chen87072a82020-03-12 16:20:12 +0800166 #define DVR_STORE_INFO_TIME (1000)
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800167 DVR_SecureBuffer_t secure_buf;
Pengfei Liuc181a982020-01-07 19:27:13 +0800168
Pengfei Liub4734232020-01-17 18:25:10 +0800169 buf = (uint8_t *)malloc(block_size);
Pengfei Liuc181a982020-01-07 19:27:13 +0800170 if (!buf) {
171 DVR_DEBUG(1, "%s, malloc failed", __func__);
172 return NULL;
173 }
174
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800175 buf_out = (uint8_t *)malloc(block_size + 188);
176 if (!buf_out) {
177 DVR_DEBUG(1, "%s, malloc failed", __func__);
178 return NULL;
179 }
180
hualing chen266b9502020-04-04 17:39:39 +0800181 memset(&record_status, 0, sizeof(record_status));
182 record_status.state = DVR_RECORD_STATE_STARTED;
183 p_ctx->event_notify_fn(DVR_RECORD_EVENT_STATUS, &record_status, p_ctx->event_userdata);
184 DVR_DEBUG(1, "%s notify record status, state:%d",
185 __func__, record_status.state);
186 DVR_DEBUG(1, "%s, secure_mode:%d", __func__, p_ctx->is_secure_mode);
187
188
Pengfei Liub4734232020-01-17 18:25:10 +0800189 clock_gettime(CLOCK_MONOTONIC, &start_ts);
Pengfei Liuc181a982020-01-07 19:27:13 +0800190 while (p_ctx->state == DVR_RECORD_STATE_STARTED) {
pengfei.liuab5a2262020-02-14 17:33:40 +0800191 /* data from dmx, normal dvr case */
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800192 if (p_ctx->is_secure_mode) {
193 memset(&secure_buf, 0, sizeof(secure_buf));
194 len = record_device_read(p_ctx->dev_handle, &secure_buf, sizeof(secure_buf), 1000);
hualing chen266b9502020-04-04 17:39:39 +0800195 if (len != DVR_FAILURE) {
196 DVR_DEBUG(1, "%s, secure_buf:%#x, size:%#x", __func__, secure_buf.addr, secure_buf.len);
197 }
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800198 } else {
199 len = record_device_read(p_ctx->dev_handle, buf, block_size, 1000);
200 }
Pengfei Liub4734232020-01-17 18:25:10 +0800201 if (len == DVR_FAILURE) {
202 usleep(10*1000);
203 continue;
204 }
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800205
206 /* Got data from device, record it */
207 if (p_ctx->enc_func) {
208 /* Encrypt record data */
pengfei.liu27cc4ec2020-04-03 16:28:16 +0800209#if 0
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800210 uint8_t *input_buf;
211 uint32_t input_len;
212 /* Out buffer length may not equal in buffer length */
213 if (p_ctx->is_secure_mode) {
214 input_buf = (uint8_t *)secure_buf.addr;
215 input_len = secure_buf.len;
216 } else {
217 input_buf = buf;
218 input_len = len;
219 }
220 out_len = block_size + 188;
221 p_ctx->enc_func(input_buf, input_len, buf_out, &out_len, p_ctx->enc_userdata);
222 ret = segment_write(p_ctx->segment_handle, buf_out, out_len);
223 len = out_len;
pengfei.liu27cc4ec2020-04-03 16:28:16 +0800224#else
225 DVR_CryptoParams_t crypto_params;
226
227 memset(&crypto_params, 0, sizeof(crypto_params));
228 crypto_params.type = DVR_CRYPTO_TYPE_ENCRYPT;
229 memcpy(crypto_params.location, p_ctx->location, strlen(p_ctx->location));
230 crypto_params.segment_id = p_ctx->segment_info.id;
231 crypto_params.offset = p_ctx->segment_info.size;
232
233 if (p_ctx->is_secure_mode) {
234 crypto_params.input_buffer.type = DVR_BUFFER_TYPE_SECURE;
235 crypto_params.input_buffer.addr = secure_buf.addr;
236 crypto_params.input_buffer.size = secure_buf.len;
237 } else {
238 crypto_params.input_buffer.type = DVR_BUFFER_TYPE_NORMAL;
239 crypto_params.input_buffer.addr = (size_t)buf;
240 crypto_params.input_buffer.size = len;
241 }
242
243 crypto_params.output_buffer.type = DVR_BUFFER_TYPE_NORMAL;
244 crypto_params.output_buffer.addr = (size_t)buf_out;
245 crypto_params.output_buffer.size = block_size + 188;
246
247 p_ctx->enc_func(&crypto_params, p_ctx->enc_userdata);
248 /* Out buffer length may not equal in buffer length */
249 ret = segment_write(p_ctx->segment_handle, buf_out, crypto_params.output_size);
250 len = crypto_params.output_size;
251#endif
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800252 } else {
253 ret = segment_write(p_ctx->segment_handle, buf, len);
254 }
hualing chen626204e2020-04-07 11:55:08 +0800255 //add DVR_RECORD_EVENT_WRITE_ERROR event if write error
256 if (ret == -1 && len > 0) {
257 //send write event
258 p_ctx->event_notify_fn(DVR_RECORD_EVENT_WRITE_ERROR, NULL, p_ctx->event_userdata);
259 DVR_DEBUG(1, "%s notify DVR_RECORD_EVENT_WRITE_ERROR, exit record thread");
260 goto end;
261 }
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800262 /* Do time index */
263 uint8_t *index_buf = p_ctx->enc_func ? buf_out : buf;
pengfei.liuab5a2262020-02-14 17:33:40 +0800264 pos = segment_tell_position(p_ctx->segment_handle);
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800265 has_pcr = record_do_pcr_index(p_ctx, index_buf, len);
pengfei.liuab5a2262020-02-14 17:33:40 +0800266 if (has_pcr == 0 && index_type == DVR_INDEX_TYPE_INVALID) {
267 clock_gettime(CLOCK_MONOTONIC, &end_ts);
268 if ((end_ts.tv_sec*1000 + end_ts.tv_nsec/1000000) -
269 (start_ts.tv_sec*1000 + start_ts.tv_nsec/1000000) > 40) {
270 /* PCR interval threshlod > 40 ms*/
271 DVR_DEBUG(1, "%s use local clock time index", __func__);
272 index_type = DVR_INDEX_TYPE_LOCAL_CLOCK;
273 }
274 } else if (has_pcr && index_type == DVR_INDEX_TYPE_INVALID){
275 DVR_DEBUG(1, "%s use pcr time index", __func__);
276 index_type = DVR_INDEX_TYPE_PCR;
Pengfei Liuc181a982020-01-07 19:27:13 +0800277 }
pengfei.liuab5a2262020-02-14 17:33:40 +0800278
279 /* Update segment info */
Pengfei Liub4734232020-01-17 18:25:10 +0800280 p_ctx->segment_info.size += len;
pengfei.liuab5a2262020-02-14 17:33:40 +0800281 /*Duration need use pcr to calculate, todo...*/
282 if (index_type == DVR_INDEX_TYPE_PCR) {
pengfei.liu8b563292020-02-26 15:49:02 +0800283 p_ctx->segment_info.duration = segment_tell_total_time(p_ctx->segment_handle);
hualing chen87072a82020-03-12 16:20:12 +0800284 if (pre_time == 0)
285 pre_time = p_ctx->segment_info.duration;
pengfei.liuab5a2262020-02-14 17:33:40 +0800286 } else if (index_type == DVR_INDEX_TYPE_LOCAL_CLOCK) {
287 clock_gettime(CLOCK_MONOTONIC, &end_ts);
288 p_ctx->segment_info.duration = (end_ts.tv_sec*1000 + end_ts.tv_nsec/1000000) -
289 (start_ts.tv_sec*1000 + start_ts.tv_nsec/1000000);
hualing chen87072a82020-03-12 16:20:12 +0800290 if (pre_time == 0)
291 pre_time = p_ctx->segment_info.duration;
pengfei.liuab5a2262020-02-14 17:33:40 +0800292 segment_update_pts(p_ctx->segment_handle, p_ctx->segment_info.duration, pos);
293 } else {
294 DVR_DEBUG(1, "%s can NOT do time index", __func__);
295 }
296 p_ctx->segment_info.nb_packets = p_ctx->segment_info.size/188;
Pengfei Liub4734232020-01-17 18:25:10 +0800297
hualing chen87072a82020-03-12 16:20:12 +0800298 if (p_ctx->segment_info.duration - pre_time > DVR_STORE_INFO_TIME) {
299 pre_time = p_ctx->segment_info.duration + DVR_STORE_INFO_TIME;
300 segment_store_info(p_ctx->segment_handle, &(p_ctx->segment_info));
301 }
302 /*Event notification*/
Pengfei Liub4734232020-01-17 18:25:10 +0800303 if (p_ctx->notification_size &&
304 p_ctx->event_notify_fn &&
hualing chen2615aa82020-04-02 21:32:51 +0800305 /*!(p_ctx->segment_info.size % p_ctx->notification_size)*/
306 (p_ctx->segment_info.size -p_ctx->last_send_size) >= p_ctx->notification_size&&
pengfei.liuab5a2262020-02-14 17:33:40 +0800307 p_ctx->segment_info.duration > 0) {
Pengfei Liub4734232020-01-17 18:25:10 +0800308 memset(&record_status, 0, sizeof(record_status));
pengfei.liuab5a2262020-02-14 17:33:40 +0800309 //clock_gettime(CLOCK_MONOTONIC, &end_ts);
hualing chen2615aa82020-04-02 21:32:51 +0800310 p_ctx->last_send_size = p_ctx->segment_info.size;
Pengfei Liub4734232020-01-17 18:25:10 +0800311 record_status.state = p_ctx->state;
312 record_status.info.id = p_ctx->segment_info.id;
pengfei.liuab5a2262020-02-14 17:33:40 +0800313 record_status.info.duration = p_ctx->segment_info.duration;
Pengfei Liub4734232020-01-17 18:25:10 +0800314 record_status.info.size = p_ctx->segment_info.size;
315 record_status.info.nb_packets = p_ctx->segment_info.size/188;
316 p_ctx->event_notify_fn(DVR_RECORD_EVENT_STATUS, &record_status, p_ctx->event_userdata);
317 DVR_DEBUG(1, "%s notify record status, state:%d, id:%lld, duration:%ld ms, size:%zu",
318 __func__, record_status.state, record_status.info.id, record_status.info.duration, record_status.info.size);
319 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800320 }
hualing chen626204e2020-04-07 11:55:08 +0800321end:
Pengfei Liub4734232020-01-17 18:25:10 +0800322 free((void *)buf);
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800323 free((void *)buf_out);
Pengfei Liub4734232020-01-17 18:25:10 +0800324 DVR_DEBUG(1, "exit %s", __func__);
Pengfei Liuc181a982020-01-07 19:27:13 +0800325 return NULL;
326}
327
328int dvr_record_open(DVR_RecordHandle_t *p_handle, DVR_RecordOpenParams_t *params)
329{
330 DVR_RecordContext_t *p_ctx;
331 Record_DeviceOpenParams_t dev_open_params;
332 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800333 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800334
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800335 DVR_RETURN_IF_FALSE(p_handle);
336 DVR_RETURN_IF_FALSE(params);
Pengfei Liuc181a982020-01-07 19:27:13 +0800337
338 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
Pengfei Liub4734232020-01-17 18:25:10 +0800339 if (record_ctx[i].state == DVR_RECORD_STATE_CLOSED) {
Pengfei Liuc181a982020-01-07 19:27:13 +0800340 break;
341 }
342 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800343 DVR_RETURN_IF_FALSE(record_ctx[i].state == DVR_RECORD_STATE_CLOSED);
Pengfei Liuc181a982020-01-07 19:27:13 +0800344 p_ctx = &record_ctx[i];
Pengfei Liub4734232020-01-17 18:25:10 +0800345 DVR_DEBUG(1, "%s , current state:%d, dmx_id:%d, notification_size:%zu", __func__,
346 p_ctx->state, params->dmx_dev_id, params->notification_size);
Pengfei Liuc181a982020-01-07 19:27:13 +0800347
Pengfei Liub4734232020-01-17 18:25:10 +0800348 /*Process event params*/
349 p_ctx->notification_size = params->notification_size;
350 p_ctx->event_notify_fn = params->event_fn;
351 p_ctx->event_userdata = params->event_userdata;
hualing chen2615aa82020-04-02 21:32:51 +0800352 p_ctx->last_send_size = 0;
Pengfei Liub4734232020-01-17 18:25:10 +0800353 /*Process crypto params, todo*/
354#if 0
355 DVR_CryptoPeriod_t crypto_period; /**< DVR crypto period information*/
356 DVR_CryptoFunction_t crypto_fn; /**< DVR crypto callback function*/
357 void *crypto_data; /**< DVR crypto userdata*/
358#endif
Pengfei Liuc181a982020-01-07 19:27:13 +0800359
Pengfei Liub4734232020-01-17 18:25:10 +0800360 memset((void *)&dev_open_params, 0, sizeof(dev_open_params));
pengfei.liuab5a2262020-02-14 17:33:40 +0800361 if (params->data_from_memory) {
362 /* data from memory, VOD case */
363 p_ctx->is_vod = 1;
364 } else {
365 p_ctx->is_vod = 0;
366 /* data from dmx, normal dvr case */
hualing chen958fe4c2020-03-24 17:35:07 +0800367 dev_open_params.dmx_dev_id = params->dmx_dev_id;
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800368 dev_open_params.buf_size = (params->flush_size > 0 ? params->flush_size : RECORD_BLOCK_SIZE);
Pengfei Liub4734232020-01-17 18:25:10 +0800369
pengfei.liuab5a2262020-02-14 17:33:40 +0800370 ret = record_device_open(&p_ctx->dev_handle, &dev_open_params);
371 if (ret != DVR_SUCCESS) {
372 DVR_DEBUG(1, "%s, open record devices failed", __func__);
373 return DVR_FAILURE;
374 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800375 }
376
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800377 p_ctx->enc_func = NULL;
378 p_ctx->enc_userdata = NULL;
379 p_ctx->is_secure_mode = 0;
Pengfei Liuc181a982020-01-07 19:27:13 +0800380 p_ctx->state = DVR_RECORD_STATE_OPENED;
381
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800382 *p_handle = p_ctx;
Pengfei Liuc181a982020-01-07 19:27:13 +0800383 return DVR_SUCCESS;
384}
385
386int dvr_record_close(DVR_RecordHandle_t handle)
387{
388 DVR_RecordContext_t *p_ctx;
389 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800390 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800391
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800392 p_ctx = (DVR_RecordContext_t *)handle;
393 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
394 if (p_ctx == &record_ctx[i])
395 break;
396 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800397 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800398
Pengfei Liub4734232020-01-17 18:25:10 +0800399 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800400 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
Pengfei Liuc181a982020-01-07 19:27:13 +0800401
pengfei.liuab5a2262020-02-14 17:33:40 +0800402 if (p_ctx->is_vod) {
403 ret = DVR_SUCCESS;
404 } else {
405 ret = record_device_close(p_ctx->dev_handle);
406 if (ret != DVR_SUCCESS) {
407 DVR_DEBUG(1, "%s, failed", __func__);
408 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800409 }
410
Pengfei Liub4734232020-01-17 18:25:10 +0800411 p_ctx->state = DVR_RECORD_STATE_CLOSED;
Pengfei Liuc181a982020-01-07 19:27:13 +0800412 return ret;
413}
414
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800415#if 0
Pengfei Liuc181a982020-01-07 19:27:13 +0800416int dvr_record_register_encryption(DVR_RecordHandle_t handle,
417 DVR_CryptoFunction_t cb,
418 DVR_CryptoParams_t params,
419 void *userdata)
420{
421 return DVR_SUCCESS;
422}
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800423#endif
Pengfei Liuc181a982020-01-07 19:27:13 +0800424
425int dvr_record_start_segment(DVR_RecordHandle_t handle, DVR_RecordStartParams_t *params)
426{
427 DVR_RecordContext_t *p_ctx;
428 Segment_OpenParams_t open_params;
429 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800430 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800431
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800432 p_ctx = (DVR_RecordContext_t *)handle;
433 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
434 if (p_ctx == &record_ctx[i])
435 break;
436 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800437 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800438
Pengfei Liub4734232020-01-17 18:25:10 +0800439 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800440 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_STARTED);
441 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
442 DVR_RETURN_IF_FALSE(params);
Pengfei Liuc181a982020-01-07 19:27:13 +0800443
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800444 DVR_RETURN_IF_FALSE(strlen((const char *)params->location) < DVR_MAX_LOCATION_SIZE);
Pengfei Liuc181a982020-01-07 19:27:13 +0800445 memset(&open_params, 0, sizeof(open_params));
446 memcpy(open_params.location, params->location, strlen(params->location));
447 open_params.segment_id = params->segment.segment_id;
448 open_params.mode = SEGMENT_MODE_WRITE;
449
450 ret = segment_open(&open_params, &p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800451 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800452
Pengfei Liub4734232020-01-17 18:25:10 +0800453 /*process params*/
Pengfei Liuc181a982020-01-07 19:27:13 +0800454 {
455 memcpy(p_ctx->location, params->location, strlen(params->location));
Pengfei Liub4734232020-01-17 18:25:10 +0800456 //need all params??
Pengfei Liuc181a982020-01-07 19:27:13 +0800457 memcpy(&p_ctx->segment_params, &params->segment, sizeof(params->segment));
Pengfei Liub4734232020-01-17 18:25:10 +0800458 /*save current segment info*/
459 memset(&p_ctx->segment_info, 0, sizeof(p_ctx->segment_info));
460 p_ctx->segment_info.id = params->segment.segment_id;
461 p_ctx->segment_info.nb_pids = params->segment.nb_pids;
462 memcpy(p_ctx->segment_info.pids, params->segment.pids, params->segment.nb_pids*sizeof(DVR_StreamPid_t));
Pengfei Liuc181a982020-01-07 19:27:13 +0800463 }
464
pengfei.liuab5a2262020-02-14 17:33:40 +0800465 if (!p_ctx->is_vod) {
466 /* normal dvr case */
467 for (i = 0; i < params->segment.nb_pids; i++) {
468 ret = record_device_add_pid(p_ctx->dev_handle, params->segment.pids[i].pid);
469 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
470 }
471 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
Pengfei Liuc181a982020-01-07 19:27:13 +0800475 p_ctx->state = DVR_RECORD_STATE_STARTED;
pengfei.liuab5a2262020-02-14 17:33:40 +0800476 if (!p_ctx->is_vod)
477 pthread_create(&p_ctx->thread, NULL, record_thread, p_ctx);
Pengfei Liub4734232020-01-17 18:25:10 +0800478
Pengfei Liuc181a982020-01-07 19:27:13 +0800479 return DVR_SUCCESS;
480}
481
482int dvr_record_next_segment(DVR_RecordHandle_t handle, DVR_RecordStartParams_t *params, DVR_RecordSegmentInfo_t *p_info)
483{
484 DVR_RecordContext_t *p_ctx;
Pengfei Liub4734232020-01-17 18:25:10 +0800485 Segment_OpenParams_t open_params;
Pengfei Liuc181a982020-01-07 19:27:13 +0800486 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800487 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800488
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800489 p_ctx = (DVR_RecordContext_t *)handle;
490 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
491 if (p_ctx == &record_ctx[i])
492 break;
493 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800494 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800495
Pengfei Liub4734232020-01-17 18:25:10 +0800496 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800497 DVR_RETURN_IF_FALSE(p_ctx->state == DVR_RECORD_STATE_STARTED);
498 //DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
499 DVR_RETURN_IF_FALSE(params);
500 DVR_RETURN_IF_FALSE(p_info);
pengfei.liuab5a2262020-02-14 17:33:40 +0800501 DVR_RETURN_IF_FALSE(!p_ctx->is_vod);
Pengfei Liuc181a982020-01-07 19:27:13 +0800502
503 /*Stop the on going record segment*/
Pengfei Liub4734232020-01-17 18:25:10 +0800504 //ret = record_device_stop(p_ctx->dev_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800505 //DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800506
507 p_ctx->state = DVR_RECORD_STATE_STOPPED;
508 pthread_join(p_ctx->thread, NULL);
509
Pengfei Liub4734232020-01-17 18:25:10 +0800510 /*Update segment info*/
511 memcpy(p_info, &p_ctx->segment_info, sizeof(p_ctx->segment_info));
512
513 ret = segment_store_info(p_ctx->segment_handle, p_info);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800514 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800515
hualing chena540a7e2020-03-27 16:44:05 +0800516 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",
517 __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 +0800518
Pengfei Liub4734232020-01-17 18:25:10 +0800519 /*Close current segment*/
520 ret = segment_close(p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800521 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800522 /*Open the new record segment*/
523 memset(&open_params, 0, sizeof(open_params));
524 memcpy(open_params.location, p_ctx->location, strlen(p_ctx->location));
525 open_params.segment_id = params->segment.segment_id;
526 open_params.mode = SEGMENT_MODE_WRITE;
527
528 ret = segment_open(&open_params, &p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800529 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800530 /*process params*/
Pengfei Liuc181a982020-01-07 19:27:13 +0800531 {
Pengfei Liub4734232020-01-17 18:25:10 +0800532 //need all params??
Pengfei Liuc181a982020-01-07 19:27:13 +0800533 memcpy(&p_ctx->segment_params, &params->segment, sizeof(params->segment));
Pengfei Liub4734232020-01-17 18:25:10 +0800534 /*save current segment info*/
535 memset(&p_ctx->segment_info, 0, sizeof(p_ctx->segment_info));
536 p_ctx->segment_info.id = params->segment.segment_id;
537 memcpy(p_ctx->segment_info.pids, params->segment.pids, params->segment.nb_pids*sizeof(DVR_StreamPid_t));
Pengfei Liuc181a982020-01-07 19:27:13 +0800538 }
539
Pengfei Liub4734232020-01-17 18:25:10 +0800540 p_ctx->segment_info.nb_pids = 0;
Pengfei Liuc181a982020-01-07 19:27:13 +0800541 for (i = 0; i < params->segment.nb_pids; i++) {
Pengfei Liub4734232020-01-17 18:25:10 +0800542 switch (params->segment.pid_action[i]) {
543 case DVR_RECORD_PID_CREATE:
544 DVR_DEBUG(1, "%s create pid:%d", __func__, params->segment.pids[i].pid);
545 ret = record_device_add_pid(p_ctx->dev_handle, params->segment.pids[i].pid);
546 p_ctx->segment_info.nb_pids++;
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800547 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800548 break;
549 case DVR_RECORD_PID_KEEP:
550 DVR_DEBUG(1, "%s keep pid:%d", __func__, params->segment.pids[i].pid);
551 p_ctx->segment_info.nb_pids++;
552 break;
553 case DVR_RECORD_PID_CLOSE:
554 DVR_DEBUG(1, "%s close pid:%d", __func__, params->segment.pids[i].pid);
555 ret = record_device_remove_pid(p_ctx->dev_handle, params->segment.pids[i].pid);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800556 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800557 break;
558 default:
559 DVR_DEBUG(1, "%s wrong action pid:%d", __func__, params->segment.pids[i].pid);
560 return DVR_FAILURE;
561 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800562 }
563
Pengfei Liub4734232020-01-17 18:25:10 +0800564 //ret = record_device_start(p_ctx->dev_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800565 //DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800566
567 pthread_create(&p_ctx->thread, NULL, record_thread, p_ctx);
568 p_ctx->state = DVR_RECORD_STATE_STARTED;
569 return DVR_SUCCESS;
570}
571
572int dvr_record_stop_segment(DVR_RecordHandle_t handle, DVR_RecordSegmentInfo_t *p_info)
573{
574 DVR_RecordContext_t *p_ctx;
575 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800576 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800577
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800578 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 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800583 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800584
Pengfei Liub4734232020-01-17 18:25:10 +0800585 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800586 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_STOPPED);
587 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800588 DVR_RETURN_IF_FALSE(p_info);/*should support NULL*/
Pengfei Liuc181a982020-01-07 19:27:13 +0800589
Pengfei Liuc181a982020-01-07 19:27:13 +0800590 p_ctx->state = DVR_RECORD_STATE_STOPPED;
pengfei.liuab5a2262020-02-14 17:33:40 +0800591 if (p_ctx->is_vod) {
pengfei.liu8b563292020-02-26 15:49:02 +0800592 p_ctx->segment_info.duration = segment_tell_total_time(p_ctx->segment_handle);
pengfei.liuab5a2262020-02-14 17:33:40 +0800593 p_ctx->segment_info.duration = 10*1000; //debug, should delete it
594 } else {
595 ret = record_device_stop(p_ctx->dev_handle);
596 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
597 //p_ctx->state = DVR_RECORD_STATE_STOPPED;
598 pthread_join(p_ctx->thread, NULL);
599 }
600
Pengfei Liuc181a982020-01-07 19:27:13 +0800601
Pengfei Liub4734232020-01-17 18:25:10 +0800602 /*Update segment info*/
603 memcpy(p_info, &p_ctx->segment_info, sizeof(p_ctx->segment_info));
604
605 ret = segment_store_info(p_ctx->segment_handle, p_info);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800606 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800607
608 DVR_DEBUG(1, "%s dump segment info, id:%lld, nb_pids:%d, duration:%ld ms, size:%zu, nb_packets:%d",
609 __func__, p_info->id, p_info->nb_pids, p_info->duration, p_info->size, p_info->nb_packets);
610
Pengfei Liuc181a982020-01-07 19:27:13 +0800611 ret = segment_close(p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800612 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800613 return DVR_SUCCESS;
614}
Pengfei Liuc181a982020-01-07 19:27:13 +0800615
Pengfei Liub4734232020-01-17 18:25:10 +0800616int dvr_record_resume_segment(DVR_RecordHandle_t handle, DVR_RecordStartParams_t *params, uint64_t *p_resume_size)
617{
618 DVR_RecordContext_t *p_ctx;
619 uint32_t i;
pengfei.liuab5a2262020-02-14 17:33:40 +0800620 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800621
622 p_ctx = (DVR_RecordContext_t *)handle;
623 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
624 if (p_ctx == &record_ctx[i])
625 break;
Pengfei Liuc181a982020-01-07 19:27:13 +0800626 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800627 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
628 DVR_RETURN_IF_FALSE(params);
629 DVR_RETURN_IF_FALSE(p_resume_size);
Pengfei Liuc181a982020-01-07 19:27:13 +0800630
pengfei.liuab5a2262020-02-14 17:33:40 +0800631 DVR_DEBUG(1, "%s , current state:%d, resume size:%lld", __func__, p_ctx->state, *p_resume_size);
632 ret = dvr_record_start_segment(handle, params);
633 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
634
635 p_ctx->segment_info.size = *p_resume_size;
636
637 return DVR_SUCCESS;
638}
639
640int dvr_record_get_status(DVR_RecordHandle_t handle, DVR_RecordStatus_t *p_status)
641{
642 DVR_RecordContext_t *p_ctx;
643 int i;
644
645 p_ctx = (DVR_RecordContext_t *)handle;
646 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
647 if (p_ctx == &record_ctx[i])
648 break;
649 }
650 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
651 DVR_RETURN_IF_FALSE(p_status);
652
653 //lock
654 p_status->state = p_ctx->state;
655 p_status->info.id = p_ctx->segment_info.id;
656 p_status->info.duration = p_ctx->segment_info.duration;
657 p_status->info.size = p_ctx->segment_info.size;
658 p_status->info.nb_packets = p_ctx->segment_info.size/188;
659
660 return DVR_SUCCESS;
661}
662
663int dvr_record_write(DVR_RecordHandle_t handle, void *buffer, uint32_t len)
664{
665 DVR_RecordContext_t *p_ctx;
666 uint32_t i;
667 off_t pos = 0;
668 int ret;
669 int has_pcr;
670
671 p_ctx = (DVR_RecordContext_t *)handle;
672 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
673 if (p_ctx == &record_ctx[i])
674 break;
675 }
676 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
677 DVR_RETURN_IF_FALSE(buffer);
678 DVR_RETURN_IF_FALSE(len);
679
680 pos = segment_tell_position(p_ctx->segment_handle);
681 has_pcr = record_do_pcr_index(p_ctx, buffer, len);
682 if (has_pcr == 0) {
683 /* Pull VOD record shoud use PCR time index */
684 DVR_DEBUG(1, "%s has no pcr, can NOT do time index", __func__);
685 }
686 ret = segment_write(p_ctx->segment_handle, buffer, len);
687 p_ctx->segment_info.size += len;
688 p_ctx->segment_info.nb_packets = p_ctx->segment_info.size/188;
689
Pengfei Liuc181a982020-01-07 19:27:13 +0800690 return DVR_SUCCESS;
691}
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800692
pengfei.liu27cc4ec2020-04-03 16:28:16 +0800693int dvr_record_set_encrypt_callback(DVR_RecordHandle_t handle, DVR_CryptoFunction_t func, void *userdata)
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800694{
695 DVR_RecordContext_t *p_ctx;
696 uint32_t i;
697
698 p_ctx = (DVR_RecordContext_t *)handle;
699 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
700 if (p_ctx == &record_ctx[i])
701 break;
702 }
703 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
704 DVR_RETURN_IF_FALSE(func);
705
706 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
707 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_STARTED);
708 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
709
710 p_ctx->enc_func = func;
711 p_ctx->enc_userdata = userdata;
712 return DVR_SUCCESS;
713}
714
715int dvr_record_set_secure_buffer(DVR_RecordHandle_t handle, uint8_t *p_secure_buf, uint32_t len)
716{
717 DVR_RecordContext_t *p_ctx;
718 uint32_t i;
719 int ret;
720
721 p_ctx = (DVR_RecordContext_t *)handle;
722 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
723 if (p_ctx == &record_ctx[i])
724 break;
725 }
726 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
727 DVR_RETURN_IF_FALSE(p_secure_buf);
728 DVR_RETURN_IF_FALSE(len);
729
730 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
731 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_STARTED);
732 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
733
734 ret = record_device_set_secure_buffer(p_ctx->dev_handle, p_secure_buf, len);
735 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
736
737 p_ctx->is_secure_mode = 1;
738 return ret;
739}