blob: 41b40eb22f514125da859e400408f89ec694675a [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.liu07ddc8a2020-03-24 23:36:53 +080013#define RECORD_BLOCK_SIZE (64 * 1024)
pengfei.liuab5a2262020-02-14 17:33:40 +080014
15/**\brief DVR index file type*/
16typedef enum {
17 DVR_INDEX_TYPE_PCR, /**< DVR index file use pcr*/
18 DVR_INDEX_TYPE_LOCAL_CLOCK, /**< DVR index file use local clock*/
19 DVR_INDEX_TYPE_INVALID /**< DVR index file type invalid type*/
20} DVR_IndexType_t;
21
22/**\brief DVR VOD context*/
23typedef struct {
24 pthread_mutex_t mutex; /**< VOD mutex lock*/
25 pthread_cond_t cond; /**< VOD condition*/
26 void *buffer; /**< VOD buffer*/
27 uint32_t buf_len; /**< VOD buffer len*/
28} DVR_VodContext_t;
29
pengfei.liu07ddc8a2020-03-24 23:36:53 +080030/**\brief DVR record secure mode buffer*/
31typedef struct {
32 uint32_t addr; /**< Secure mode record buffer address*/
33 uint32_t len; /**< Secure mode record buffer length*/
34} DVR_SecureBuffer_t;
35
Pengfei Liub4734232020-01-17 18:25:10 +080036/**\brief DVR record context*/
Pengfei Liuc181a982020-01-07 19:27:13 +080037typedef struct {
Pengfei Liub4734232020-01-17 18:25:10 +080038 pthread_t thread; /**< DVR thread handle*/
39 Record_DeviceHandle_t dev_handle; /**< DVR device handle*/
40 Segment_Handle_t segment_handle; /**< DVR segment handle*/
41 DVR_RecordState_t state; /**< DVR record state*/
42 char location[DVR_MAX_LOCATION_SIZE]; /**< DVR record file location*/
43 DVR_RecordSegmentStartParams_t segment_params; /**< DVR record start parameters*/
44 DVR_RecordSegmentInfo_t segment_info; /**< DVR record current segment info*/
45 size_t notification_size; /**< DVR record nogification size*/
46 DVR_RecordEventFunction_t event_notify_fn; /**< DVR record event notify function*/
47 void *event_userdata; /**< DVR record event userdata*/
pengfei.liuab5a2262020-02-14 17:33:40 +080048 //DVR_VodContext_t vod; /**< DVR record vod context*/
49 int is_vod; /**< Indicate current mode is VOD record mode*/
pengfei.liu07ddc8a2020-03-24 23:36:53 +080050 DVR_RecordEncryptFunction_t enc_func; /**< Encrypt function*/
51 void *enc_userdata; /**< Encrypt userdata*/
52 int is_secure_mode; /**< Record session run in secure pipeline */
Pengfei Liuc181a982020-01-07 19:27:13 +080053} DVR_RecordContext_t;
54
55static DVR_RecordContext_t record_ctx[MAX_DVR_RECORD_SESSION_COUNT] = {
56 {
Pengfei Liub4734232020-01-17 18:25:10 +080057 .state = DVR_RECORD_STATE_CLOSED
Pengfei Liuc181a982020-01-07 19:27:13 +080058 },
59 {
Pengfei Liub4734232020-01-17 18:25:10 +080060 .state = DVR_RECORD_STATE_CLOSED
Pengfei Liuc181a982020-01-07 19:27:13 +080061 }
62};
63
pengfei.liuab5a2262020-02-14 17:33:40 +080064static int record_save_pcr(DVR_RecordContext_t *p_ctx, uint8_t *buf, loff_t pos)
65{
66 uint8_t *p = buf;
67 int len;
68 uint8_t afc;
69 uint64_t pcr = 0;
70 int has_pcr = 0;
71 int pid;
72 int adp_field_len;
73
74 pid = ((p[1] & 0x1f) << 8) | p[2];
75 if (pid == 0x1fff)
76 return has_pcr;
77
78 //scramble = p[3] >> 6;
79 //cc = p[3] & 0x0f;
80 afc = (p[3] >> 4) & 0x03;
81
82 p += 4;
83 len = 184;
84
85 if (afc & 2) {
86 adp_field_len = p[0];
87 /* Skip adaptation len */
88 p++;
89 len--;
90 /* Parse pcr field, see 13818 spec table I-2-6,adaptation_field */
91 if (p[0] & 0x10 && len >= 6) {
92 /* get pcr value,pcr is 33bit value */
93 pcr = (((uint64_t)(p[1])) << 25)
94 | (((uint64_t)p[2]) << 17)
95 | (((uint64_t)(p[3])) << 9)
96 | (((uint64_t)p[4]) << 1)
97 | ((((uint64_t)p[5]) & 0x80) >> 7);
98 has_pcr = 1;
99 }
100
101 p += adp_field_len;
102 len -= adp_field_len;
103
104 if (len < 0) {
105 DVR_DEBUG(1, "parser pcr: illegal adaptation field length");
106 return 0;
107 }
108 }
109
110 if (has_pcr) {
111 segment_update_pts(p_ctx->segment_handle, pcr/90, pos);
112 }
113 return has_pcr;
114}
115
116static int record_do_pcr_index(DVR_RecordContext_t *p_ctx, uint8_t *buf, int len)
117{
118 uint8_t *p = buf;
119 int left = len;
120 loff_t pos;
121 int has_pcr = 0;
122
123 pos = segment_tell_position(p_ctx->segment_handle);
124 while (left >= 188) {
125 if (*p == 0x47) {
126 has_pcr |= record_save_pcr(p_ctx, p, pos);
127 p += 188;
128 left -= 188;
129 pos += 188;
130 } else {
131 p++;
132 left --;
133 pos++;
134 }
135 }
136 return has_pcr;
137}
138
Pengfei Liuc181a982020-01-07 19:27:13 +0800139void *record_thread(void *arg)
140{
141 DVR_RecordContext_t *p_ctx = (DVR_RecordContext_t *)arg;
142 ssize_t len;
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800143 uint8_t *buf, *buf_out;
144 int block_size = RECORD_BLOCK_SIZE;//256*1024;
pengfei.liuab5a2262020-02-14 17:33:40 +0800145 loff_t pos = 0;
Pengfei Liuc181a982020-01-07 19:27:13 +0800146 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800147 struct timespec start_ts, end_ts;
148 DVR_RecordStatus_t record_status;
pengfei.liuab5a2262020-02-14 17:33:40 +0800149 int has_pcr;
150 int index_type = DVR_INDEX_TYPE_INVALID;
hualing chen87072a82020-03-12 16:20:12 +0800151 time_t pre_time = 0;
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800152 uint32_t out_len;
hualing chen87072a82020-03-12 16:20:12 +0800153 #define DVR_STORE_INFO_TIME (1000)
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800154 DVR_SecureBuffer_t secure_buf;
Pengfei Liuc181a982020-01-07 19:27:13 +0800155
Pengfei Liub4734232020-01-17 18:25:10 +0800156 buf = (uint8_t *)malloc(block_size);
Pengfei Liuc181a982020-01-07 19:27:13 +0800157 if (!buf) {
158 DVR_DEBUG(1, "%s, malloc failed", __func__);
159 return NULL;
160 }
161
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800162 buf_out = (uint8_t *)malloc(block_size + 188);
163 if (!buf_out) {
164 DVR_DEBUG(1, "%s, malloc failed", __func__);
165 return NULL;
166 }
167
Pengfei Liub4734232020-01-17 18:25:10 +0800168 clock_gettime(CLOCK_MONOTONIC, &start_ts);
Pengfei Liuc181a982020-01-07 19:27:13 +0800169 while (p_ctx->state == DVR_RECORD_STATE_STARTED) {
pengfei.liuab5a2262020-02-14 17:33:40 +0800170 /* data from dmx, normal dvr case */
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800171 if (p_ctx->is_secure_mode) {
172 memset(&secure_buf, 0, sizeof(secure_buf));
173 len = record_device_read(p_ctx->dev_handle, &secure_buf, sizeof(secure_buf), 1000);
174 } else {
175 len = record_device_read(p_ctx->dev_handle, buf, block_size, 1000);
176 }
Pengfei Liub4734232020-01-17 18:25:10 +0800177 if (len == DVR_FAILURE) {
178 usleep(10*1000);
179 continue;
180 }
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800181
182 /* Got data from device, record it */
183 if (p_ctx->enc_func) {
184 /* Encrypt record data */
185 uint8_t *input_buf;
186 uint32_t input_len;
187 /* Out buffer length may not equal in buffer length */
188 if (p_ctx->is_secure_mode) {
189 input_buf = (uint8_t *)secure_buf.addr;
190 input_len = secure_buf.len;
191 } else {
192 input_buf = buf;
193 input_len = len;
194 }
195 out_len = block_size + 188;
196 p_ctx->enc_func(input_buf, input_len, buf_out, &out_len, p_ctx->enc_userdata);
197 ret = segment_write(p_ctx->segment_handle, buf_out, out_len);
198 len = out_len;
199 } else {
200 ret = segment_write(p_ctx->segment_handle, buf, len);
201 }
202
203 /* Do time index */
204 uint8_t *index_buf = p_ctx->enc_func ? buf_out : buf;
pengfei.liuab5a2262020-02-14 17:33:40 +0800205 pos = segment_tell_position(p_ctx->segment_handle);
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800206 has_pcr = record_do_pcr_index(p_ctx, index_buf, len);
pengfei.liuab5a2262020-02-14 17:33:40 +0800207 if (has_pcr == 0 && index_type == DVR_INDEX_TYPE_INVALID) {
208 clock_gettime(CLOCK_MONOTONIC, &end_ts);
209 if ((end_ts.tv_sec*1000 + end_ts.tv_nsec/1000000) -
210 (start_ts.tv_sec*1000 + start_ts.tv_nsec/1000000) > 40) {
211 /* PCR interval threshlod > 40 ms*/
212 DVR_DEBUG(1, "%s use local clock time index", __func__);
213 index_type = DVR_INDEX_TYPE_LOCAL_CLOCK;
214 }
215 } else if (has_pcr && index_type == DVR_INDEX_TYPE_INVALID){
216 DVR_DEBUG(1, "%s use pcr time index", __func__);
217 index_type = DVR_INDEX_TYPE_PCR;
Pengfei Liuc181a982020-01-07 19:27:13 +0800218 }
pengfei.liuab5a2262020-02-14 17:33:40 +0800219
220 /* Update segment info */
Pengfei Liub4734232020-01-17 18:25:10 +0800221 p_ctx->segment_info.size += len;
pengfei.liuab5a2262020-02-14 17:33:40 +0800222 /*Duration need use pcr to calculate, todo...*/
223 if (index_type == DVR_INDEX_TYPE_PCR) {
pengfei.liu8b563292020-02-26 15:49:02 +0800224 p_ctx->segment_info.duration = segment_tell_total_time(p_ctx->segment_handle);
hualing chen87072a82020-03-12 16:20:12 +0800225 if (pre_time == 0)
226 pre_time = p_ctx->segment_info.duration;
pengfei.liuab5a2262020-02-14 17:33:40 +0800227 } else if (index_type == DVR_INDEX_TYPE_LOCAL_CLOCK) {
228 clock_gettime(CLOCK_MONOTONIC, &end_ts);
229 p_ctx->segment_info.duration = (end_ts.tv_sec*1000 + end_ts.tv_nsec/1000000) -
230 (start_ts.tv_sec*1000 + start_ts.tv_nsec/1000000);
hualing chen87072a82020-03-12 16:20:12 +0800231 if (pre_time == 0)
232 pre_time = p_ctx->segment_info.duration;
pengfei.liuab5a2262020-02-14 17:33:40 +0800233 segment_update_pts(p_ctx->segment_handle, p_ctx->segment_info.duration, pos);
234 } else {
235 DVR_DEBUG(1, "%s can NOT do time index", __func__);
236 }
237 p_ctx->segment_info.nb_packets = p_ctx->segment_info.size/188;
Pengfei Liub4734232020-01-17 18:25:10 +0800238
hualing chen87072a82020-03-12 16:20:12 +0800239 if (p_ctx->segment_info.duration - pre_time > DVR_STORE_INFO_TIME) {
240 pre_time = p_ctx->segment_info.duration + DVR_STORE_INFO_TIME;
241 segment_store_info(p_ctx->segment_handle, &(p_ctx->segment_info));
242 }
243 /*Event notification*/
Pengfei Liub4734232020-01-17 18:25:10 +0800244 if (p_ctx->notification_size &&
245 p_ctx->event_notify_fn &&
pengfei.liuab5a2262020-02-14 17:33:40 +0800246 !(p_ctx->segment_info.size % p_ctx->notification_size) &&
247 p_ctx->segment_info.duration > 0) {
Pengfei Liub4734232020-01-17 18:25:10 +0800248 memset(&record_status, 0, sizeof(record_status));
pengfei.liuab5a2262020-02-14 17:33:40 +0800249 //clock_gettime(CLOCK_MONOTONIC, &end_ts);
Pengfei Liub4734232020-01-17 18:25:10 +0800250
251 record_status.state = p_ctx->state;
252 record_status.info.id = p_ctx->segment_info.id;
pengfei.liuab5a2262020-02-14 17:33:40 +0800253 record_status.info.duration = p_ctx->segment_info.duration;
Pengfei Liub4734232020-01-17 18:25:10 +0800254 record_status.info.size = p_ctx->segment_info.size;
255 record_status.info.nb_packets = p_ctx->segment_info.size/188;
256 p_ctx->event_notify_fn(DVR_RECORD_EVENT_STATUS, &record_status, p_ctx->event_userdata);
257 DVR_DEBUG(1, "%s notify record status, state:%d, id:%lld, duration:%ld ms, size:%zu",
258 __func__, record_status.state, record_status.info.id, record_status.info.duration, record_status.info.size);
259 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800260 }
261
Pengfei Liub4734232020-01-17 18:25:10 +0800262 free((void *)buf);
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800263 free((void *)buf_out);
Pengfei Liub4734232020-01-17 18:25:10 +0800264 DVR_DEBUG(1, "exit %s", __func__);
Pengfei Liuc181a982020-01-07 19:27:13 +0800265 return NULL;
266}
267
268int dvr_record_open(DVR_RecordHandle_t *p_handle, DVR_RecordOpenParams_t *params)
269{
270 DVR_RecordContext_t *p_ctx;
271 Record_DeviceOpenParams_t dev_open_params;
272 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800273 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800274
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800275 DVR_RETURN_IF_FALSE(p_handle);
276 DVR_RETURN_IF_FALSE(params);
Pengfei Liuc181a982020-01-07 19:27:13 +0800277
278 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
Pengfei Liub4734232020-01-17 18:25:10 +0800279 if (record_ctx[i].state == DVR_RECORD_STATE_CLOSED) {
Pengfei Liuc181a982020-01-07 19:27:13 +0800280 break;
281 }
282 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800283 DVR_RETURN_IF_FALSE(record_ctx[i].state == DVR_RECORD_STATE_CLOSED);
Pengfei Liuc181a982020-01-07 19:27:13 +0800284 p_ctx = &record_ctx[i];
Pengfei Liub4734232020-01-17 18:25:10 +0800285 DVR_DEBUG(1, "%s , current state:%d, dmx_id:%d, notification_size:%zu", __func__,
286 p_ctx->state, params->dmx_dev_id, params->notification_size);
Pengfei Liuc181a982020-01-07 19:27:13 +0800287
Pengfei Liub4734232020-01-17 18:25:10 +0800288 /*Process event params*/
289 p_ctx->notification_size = params->notification_size;
290 p_ctx->event_notify_fn = params->event_fn;
291 p_ctx->event_userdata = params->event_userdata;
292 /*Process crypto params, todo*/
293#if 0
294 DVR_CryptoPeriod_t crypto_period; /**< DVR crypto period information*/
295 DVR_CryptoFunction_t crypto_fn; /**< DVR crypto callback function*/
296 void *crypto_data; /**< DVR crypto userdata*/
297#endif
Pengfei Liuc181a982020-01-07 19:27:13 +0800298
Pengfei Liub4734232020-01-17 18:25:10 +0800299 memset((void *)&dev_open_params, 0, sizeof(dev_open_params));
pengfei.liuab5a2262020-02-14 17:33:40 +0800300 if (params->data_from_memory) {
301 /* data from memory, VOD case */
302 p_ctx->is_vod = 1;
303 } else {
304 p_ctx->is_vod = 0;
305 /* data from dmx, normal dvr case */
hualing chen958fe4c2020-03-24 17:35:07 +0800306 dev_open_params.dmx_dev_id = params->dmx_dev_id;
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800307 dev_open_params.buf_size = (params->flush_size > 0 ? params->flush_size : RECORD_BLOCK_SIZE);
Pengfei Liub4734232020-01-17 18:25:10 +0800308
pengfei.liuab5a2262020-02-14 17:33:40 +0800309 ret = record_device_open(&p_ctx->dev_handle, &dev_open_params);
310 if (ret != DVR_SUCCESS) {
311 DVR_DEBUG(1, "%s, open record devices failed", __func__);
312 return DVR_FAILURE;
313 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800314 }
315
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800316 p_ctx->enc_func = NULL;
317 p_ctx->enc_userdata = NULL;
318 p_ctx->is_secure_mode = 0;
Pengfei Liuc181a982020-01-07 19:27:13 +0800319 p_ctx->state = DVR_RECORD_STATE_OPENED;
320
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800321 *p_handle = p_ctx;
Pengfei Liuc181a982020-01-07 19:27:13 +0800322 return DVR_SUCCESS;
323}
324
325int dvr_record_close(DVR_RecordHandle_t handle)
326{
327 DVR_RecordContext_t *p_ctx;
328 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800329 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800330
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800331 p_ctx = (DVR_RecordContext_t *)handle;
332 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
333 if (p_ctx == &record_ctx[i])
334 break;
335 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800336 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800337
Pengfei Liub4734232020-01-17 18:25:10 +0800338 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800339 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
Pengfei Liuc181a982020-01-07 19:27:13 +0800340
pengfei.liuab5a2262020-02-14 17:33:40 +0800341 if (p_ctx->is_vod) {
342 ret = DVR_SUCCESS;
343 } else {
344 ret = record_device_close(p_ctx->dev_handle);
345 if (ret != DVR_SUCCESS) {
346 DVR_DEBUG(1, "%s, failed", __func__);
347 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800348 }
349
Pengfei Liub4734232020-01-17 18:25:10 +0800350 p_ctx->state = DVR_RECORD_STATE_CLOSED;
Pengfei Liuc181a982020-01-07 19:27:13 +0800351 return ret;
352}
353
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800354#if 0
Pengfei Liuc181a982020-01-07 19:27:13 +0800355int dvr_record_register_encryption(DVR_RecordHandle_t handle,
356 DVR_CryptoFunction_t cb,
357 DVR_CryptoParams_t params,
358 void *userdata)
359{
360 return DVR_SUCCESS;
361}
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800362#endif
Pengfei Liuc181a982020-01-07 19:27:13 +0800363
364int dvr_record_start_segment(DVR_RecordHandle_t handle, DVR_RecordStartParams_t *params)
365{
366 DVR_RecordContext_t *p_ctx;
367 Segment_OpenParams_t open_params;
368 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800369 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800370
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800371 p_ctx = (DVR_RecordContext_t *)handle;
372 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
373 if (p_ctx == &record_ctx[i])
374 break;
375 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800376 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800377
Pengfei Liub4734232020-01-17 18:25:10 +0800378 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800379 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_STARTED);
380 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
381 DVR_RETURN_IF_FALSE(params);
Pengfei Liuc181a982020-01-07 19:27:13 +0800382
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800383 DVR_RETURN_IF_FALSE(strlen((const char *)params->location) < DVR_MAX_LOCATION_SIZE);
Pengfei Liuc181a982020-01-07 19:27:13 +0800384 memset(&open_params, 0, sizeof(open_params));
385 memcpy(open_params.location, params->location, strlen(params->location));
386 open_params.segment_id = params->segment.segment_id;
387 open_params.mode = SEGMENT_MODE_WRITE;
388
389 ret = segment_open(&open_params, &p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800390 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800391
Pengfei Liub4734232020-01-17 18:25:10 +0800392 /*process params*/
Pengfei Liuc181a982020-01-07 19:27:13 +0800393 {
394 memcpy(p_ctx->location, params->location, strlen(params->location));
Pengfei Liub4734232020-01-17 18:25:10 +0800395 //need all params??
Pengfei Liuc181a982020-01-07 19:27:13 +0800396 memcpy(&p_ctx->segment_params, &params->segment, sizeof(params->segment));
Pengfei Liub4734232020-01-17 18:25:10 +0800397 /*save current segment info*/
398 memset(&p_ctx->segment_info, 0, sizeof(p_ctx->segment_info));
399 p_ctx->segment_info.id = params->segment.segment_id;
400 p_ctx->segment_info.nb_pids = params->segment.nb_pids;
401 memcpy(p_ctx->segment_info.pids, params->segment.pids, params->segment.nb_pids*sizeof(DVR_StreamPid_t));
Pengfei Liuc181a982020-01-07 19:27:13 +0800402 }
403
pengfei.liuab5a2262020-02-14 17:33:40 +0800404 if (!p_ctx->is_vod) {
405 /* normal dvr case */
406 for (i = 0; i < params->segment.nb_pids; i++) {
407 ret = record_device_add_pid(p_ctx->dev_handle, params->segment.pids[i].pid);
408 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
409 }
410 ret = record_device_start(p_ctx->dev_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800411 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800412 }
413
Pengfei Liuc181a982020-01-07 19:27:13 +0800414 p_ctx->state = DVR_RECORD_STATE_STARTED;
pengfei.liuab5a2262020-02-14 17:33:40 +0800415 if (!p_ctx->is_vod)
416 pthread_create(&p_ctx->thread, NULL, record_thread, p_ctx);
Pengfei Liub4734232020-01-17 18:25:10 +0800417
Pengfei Liuc181a982020-01-07 19:27:13 +0800418 return DVR_SUCCESS;
419}
420
421int dvr_record_next_segment(DVR_RecordHandle_t handle, DVR_RecordStartParams_t *params, DVR_RecordSegmentInfo_t *p_info)
422{
423 DVR_RecordContext_t *p_ctx;
Pengfei Liub4734232020-01-17 18:25:10 +0800424 Segment_OpenParams_t open_params;
Pengfei Liuc181a982020-01-07 19:27:13 +0800425 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800426 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800427
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800428 p_ctx = (DVR_RecordContext_t *)handle;
429 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
430 if (p_ctx == &record_ctx[i])
431 break;
432 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800433 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800434
Pengfei Liub4734232020-01-17 18:25:10 +0800435 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800436 DVR_RETURN_IF_FALSE(p_ctx->state == DVR_RECORD_STATE_STARTED);
437 //DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
438 DVR_RETURN_IF_FALSE(params);
439 DVR_RETURN_IF_FALSE(p_info);
pengfei.liuab5a2262020-02-14 17:33:40 +0800440 DVR_RETURN_IF_FALSE(!p_ctx->is_vod);
Pengfei Liuc181a982020-01-07 19:27:13 +0800441
442 /*Stop the on going record segment*/
Pengfei Liub4734232020-01-17 18:25:10 +0800443 //ret = record_device_stop(p_ctx->dev_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800444 //DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800445
446 p_ctx->state = DVR_RECORD_STATE_STOPPED;
447 pthread_join(p_ctx->thread, NULL);
448
Pengfei Liub4734232020-01-17 18:25:10 +0800449 /*Update segment info*/
450 memcpy(p_info, &p_ctx->segment_info, sizeof(p_ctx->segment_info));
451
452 ret = segment_store_info(p_ctx->segment_handle, p_info);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800453 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800454
hualing chena540a7e2020-03-27 16:44:05 +0800455 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",
456 __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 +0800457
Pengfei Liub4734232020-01-17 18:25:10 +0800458 /*Close current segment*/
459 ret = segment_close(p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800460 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800461 /*Open the new record segment*/
462 memset(&open_params, 0, sizeof(open_params));
463 memcpy(open_params.location, p_ctx->location, strlen(p_ctx->location));
464 open_params.segment_id = params->segment.segment_id;
465 open_params.mode = SEGMENT_MODE_WRITE;
466
467 ret = segment_open(&open_params, &p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800468 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800469 /*process params*/
Pengfei Liuc181a982020-01-07 19:27:13 +0800470 {
Pengfei Liub4734232020-01-17 18:25:10 +0800471 //need all params??
Pengfei Liuc181a982020-01-07 19:27:13 +0800472 memcpy(&p_ctx->segment_params, &params->segment, sizeof(params->segment));
Pengfei Liub4734232020-01-17 18:25:10 +0800473 /*save current segment info*/
474 memset(&p_ctx->segment_info, 0, sizeof(p_ctx->segment_info));
475 p_ctx->segment_info.id = params->segment.segment_id;
476 memcpy(p_ctx->segment_info.pids, params->segment.pids, params->segment.nb_pids*sizeof(DVR_StreamPid_t));
Pengfei Liuc181a982020-01-07 19:27:13 +0800477 }
478
Pengfei Liub4734232020-01-17 18:25:10 +0800479 p_ctx->segment_info.nb_pids = 0;
Pengfei Liuc181a982020-01-07 19:27:13 +0800480 for (i = 0; i < params->segment.nb_pids; i++) {
Pengfei Liub4734232020-01-17 18:25:10 +0800481 switch (params->segment.pid_action[i]) {
482 case DVR_RECORD_PID_CREATE:
483 DVR_DEBUG(1, "%s create pid:%d", __func__, params->segment.pids[i].pid);
484 ret = record_device_add_pid(p_ctx->dev_handle, params->segment.pids[i].pid);
485 p_ctx->segment_info.nb_pids++;
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800486 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800487 break;
488 case DVR_RECORD_PID_KEEP:
489 DVR_DEBUG(1, "%s keep pid:%d", __func__, params->segment.pids[i].pid);
490 p_ctx->segment_info.nb_pids++;
491 break;
492 case DVR_RECORD_PID_CLOSE:
493 DVR_DEBUG(1, "%s close pid:%d", __func__, params->segment.pids[i].pid);
494 ret = record_device_remove_pid(p_ctx->dev_handle, params->segment.pids[i].pid);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800495 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800496 break;
497 default:
498 DVR_DEBUG(1, "%s wrong action pid:%d", __func__, params->segment.pids[i].pid);
499 return DVR_FAILURE;
500 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800501 }
502
Pengfei Liub4734232020-01-17 18:25:10 +0800503 //ret = record_device_start(p_ctx->dev_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800504 //DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800505
506 pthread_create(&p_ctx->thread, NULL, record_thread, p_ctx);
507 p_ctx->state = DVR_RECORD_STATE_STARTED;
508 return DVR_SUCCESS;
509}
510
511int dvr_record_stop_segment(DVR_RecordHandle_t handle, DVR_RecordSegmentInfo_t *p_info)
512{
513 DVR_RecordContext_t *p_ctx;
514 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800515 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800516
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800517 p_ctx = (DVR_RecordContext_t *)handle;
518 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
519 if (p_ctx == &record_ctx[i])
520 break;
521 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800522 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800523
Pengfei Liub4734232020-01-17 18:25:10 +0800524 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800525 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_STOPPED);
526 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
527 DVR_RETURN_IF_FALSE(p_info);
Pengfei Liuc181a982020-01-07 19:27:13 +0800528
Pengfei Liuc181a982020-01-07 19:27:13 +0800529 p_ctx->state = DVR_RECORD_STATE_STOPPED;
pengfei.liuab5a2262020-02-14 17:33:40 +0800530 if (p_ctx->is_vod) {
pengfei.liu8b563292020-02-26 15:49:02 +0800531 p_ctx->segment_info.duration = segment_tell_total_time(p_ctx->segment_handle);
pengfei.liuab5a2262020-02-14 17:33:40 +0800532 p_ctx->segment_info.duration = 10*1000; //debug, should delete it
533 } else {
534 ret = record_device_stop(p_ctx->dev_handle);
535 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
536 //p_ctx->state = DVR_RECORD_STATE_STOPPED;
537 pthread_join(p_ctx->thread, NULL);
538 }
539
Pengfei Liuc181a982020-01-07 19:27:13 +0800540
Pengfei Liub4734232020-01-17 18:25:10 +0800541 /*Update segment info*/
542 memcpy(p_info, &p_ctx->segment_info, sizeof(p_ctx->segment_info));
543
544 ret = segment_store_info(p_ctx->segment_handle, p_info);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800545 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800546
547 DVR_DEBUG(1, "%s dump segment info, id:%lld, nb_pids:%d, duration:%ld ms, size:%zu, nb_packets:%d",
548 __func__, p_info->id, p_info->nb_pids, p_info->duration, p_info->size, p_info->nb_packets);
549
Pengfei Liuc181a982020-01-07 19:27:13 +0800550 ret = segment_close(p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800551 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800552 return DVR_SUCCESS;
553}
Pengfei Liuc181a982020-01-07 19:27:13 +0800554
Pengfei Liub4734232020-01-17 18:25:10 +0800555int dvr_record_resume_segment(DVR_RecordHandle_t handle, DVR_RecordStartParams_t *params, uint64_t *p_resume_size)
556{
557 DVR_RecordContext_t *p_ctx;
558 uint32_t i;
pengfei.liuab5a2262020-02-14 17:33:40 +0800559 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800560
561 p_ctx = (DVR_RecordContext_t *)handle;
562 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
563 if (p_ctx == &record_ctx[i])
564 break;
Pengfei Liuc181a982020-01-07 19:27:13 +0800565 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800566 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
567 DVR_RETURN_IF_FALSE(params);
568 DVR_RETURN_IF_FALSE(p_resume_size);
Pengfei Liuc181a982020-01-07 19:27:13 +0800569
pengfei.liuab5a2262020-02-14 17:33:40 +0800570 DVR_DEBUG(1, "%s , current state:%d, resume size:%lld", __func__, p_ctx->state, *p_resume_size);
571 ret = dvr_record_start_segment(handle, params);
572 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
573
574 p_ctx->segment_info.size = *p_resume_size;
575
576 return DVR_SUCCESS;
577}
578
579int dvr_record_get_status(DVR_RecordHandle_t handle, DVR_RecordStatus_t *p_status)
580{
581 DVR_RecordContext_t *p_ctx;
582 int i;
583
584 p_ctx = (DVR_RecordContext_t *)handle;
585 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
586 if (p_ctx == &record_ctx[i])
587 break;
588 }
589 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
590 DVR_RETURN_IF_FALSE(p_status);
591
592 //lock
593 p_status->state = p_ctx->state;
594 p_status->info.id = p_ctx->segment_info.id;
595 p_status->info.duration = p_ctx->segment_info.duration;
596 p_status->info.size = p_ctx->segment_info.size;
597 p_status->info.nb_packets = p_ctx->segment_info.size/188;
598
599 return DVR_SUCCESS;
600}
601
602int dvr_record_write(DVR_RecordHandle_t handle, void *buffer, uint32_t len)
603{
604 DVR_RecordContext_t *p_ctx;
605 uint32_t i;
606 off_t pos = 0;
607 int ret;
608 int has_pcr;
609
610 p_ctx = (DVR_RecordContext_t *)handle;
611 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
612 if (p_ctx == &record_ctx[i])
613 break;
614 }
615 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
616 DVR_RETURN_IF_FALSE(buffer);
617 DVR_RETURN_IF_FALSE(len);
618
619 pos = segment_tell_position(p_ctx->segment_handle);
620 has_pcr = record_do_pcr_index(p_ctx, buffer, len);
621 if (has_pcr == 0) {
622 /* Pull VOD record shoud use PCR time index */
623 DVR_DEBUG(1, "%s has no pcr, can NOT do time index", __func__);
624 }
625 ret = segment_write(p_ctx->segment_handle, buffer, len);
626 p_ctx->segment_info.size += len;
627 p_ctx->segment_info.nb_packets = p_ctx->segment_info.size/188;
628
Pengfei Liuc181a982020-01-07 19:27:13 +0800629 return DVR_SUCCESS;
630}
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800631
632int dvr_record_set_encrypt_callback(DVR_RecordHandle_t handle, DVR_RecordEncryptFunction_t func, void *userdata)
633{
634 DVR_RecordContext_t *p_ctx;
635 uint32_t i;
636
637 p_ctx = (DVR_RecordContext_t *)handle;
638 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
639 if (p_ctx == &record_ctx[i])
640 break;
641 }
642 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
643 DVR_RETURN_IF_FALSE(func);
644
645 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
646 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_STARTED);
647 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
648
649 p_ctx->enc_func = func;
650 p_ctx->enc_userdata = userdata;
651 return DVR_SUCCESS;
652}
653
654int dvr_record_set_secure_buffer(DVR_RecordHandle_t handle, uint8_t *p_secure_buf, uint32_t len)
655{
656 DVR_RecordContext_t *p_ctx;
657 uint32_t i;
658 int ret;
659
660 p_ctx = (DVR_RecordContext_t *)handle;
661 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
662 if (p_ctx == &record_ctx[i])
663 break;
664 }
665 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
666 DVR_RETURN_IF_FALSE(p_secure_buf);
667 DVR_RETURN_IF_FALSE(len);
668
669 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
670 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_STARTED);
671 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
672
673 ret = record_device_set_secure_buffer(p_ctx->dev_handle, p_secure_buf, len);
674 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
675
676 p_ctx->is_secure_mode = 1;
677 return ret;
678}