blob: c0cbabb0ca9d5ee2760334aba732c2b38ccd165d [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"
Gong Ke2a0ebbe2021-05-25 15:22:50 +08009#include "dvb_utils.h"
Pengfei Liuc181a982020-01-07 19:27:13 +080010#include "record_device.h"
11#include "segment.h"
pengfei.liu567d6d82020-04-17 16:48:59 +080012#include <sys/time.h>
Pengfei Liuc181a982020-01-07 19:27:13 +080013
hualing chend241c7a2021-06-22 13:34:27 +080014#define CONTROL_SPEED_ENABLE 0
15
hualing chenc7aa4c82021-02-03 15:41:37 +080016//#define DEBUG_PERFORMANCE
Pengfei Liuc181a982020-01-07 19:27:13 +080017#define MAX_DVR_RECORD_SESSION_COUNT 2
hualing chen266b9502020-04-04 17:39:39 +080018#define RECORD_BLOCK_SIZE (256 * 1024)
Yahui Hance15e9c2020-12-08 18:08:32 +080019#define NEW_DEVICE_RECORD_BLOCK_SIZE (1024 * 188)
pengfei.liuab5a2262020-02-14 17:33:40 +080020
21/**\brief DVR index file type*/
22typedef enum {
23 DVR_INDEX_TYPE_PCR, /**< DVR index file use pcr*/
24 DVR_INDEX_TYPE_LOCAL_CLOCK, /**< DVR index file use local clock*/
25 DVR_INDEX_TYPE_INVALID /**< DVR index file type invalid type*/
26} DVR_IndexType_t;
27
28/**\brief DVR VOD context*/
29typedef struct {
30 pthread_mutex_t mutex; /**< VOD mutex lock*/
31 pthread_cond_t cond; /**< VOD condition*/
32 void *buffer; /**< VOD buffer*/
33 uint32_t buf_len; /**< VOD buffer len*/
34} DVR_VodContext_t;
35
pengfei.liu07ddc8a2020-03-24 23:36:53 +080036/**\brief DVR record secure mode buffer*/
37typedef struct {
38 uint32_t addr; /**< Secure mode record buffer address*/
39 uint32_t len; /**< Secure mode record buffer length*/
40} DVR_SecureBuffer_t;
41
hualing chenf9867402020-09-23 17:06:20 +080042/**\brief DVR record new dmx secure mode buffer*/
43typedef struct {
44 uint32_t buf_start; /**< Secure mode record buffer address*/
45 uint32_t buf_end; /**< Secure mode record buffer length*/
46 uint32_t data_start; /**< Secure mode record buffer address*/
47 uint32_t data_end; /**< Secure mode record buffer length*/
48} DVR_NewDmxSecureBuffer_t;
49
Pengfei Liub4734232020-01-17 18:25:10 +080050/**\brief DVR record context*/
Pengfei Liuc181a982020-01-07 19:27:13 +080051typedef struct {
Pengfei Liub4734232020-01-17 18:25:10 +080052 pthread_t thread; /**< DVR thread handle*/
53 Record_DeviceHandle_t dev_handle; /**< DVR device handle*/
54 Segment_Handle_t segment_handle; /**< DVR segment handle*/
55 DVR_RecordState_t state; /**< DVR record state*/
56 char location[DVR_MAX_LOCATION_SIZE]; /**< DVR record file location*/
57 DVR_RecordSegmentStartParams_t segment_params; /**< DVR record start parameters*/
58 DVR_RecordSegmentInfo_t segment_info; /**< DVR record current segment info*/
59 size_t notification_size; /**< DVR record nogification size*/
60 DVR_RecordEventFunction_t event_notify_fn; /**< DVR record event notify function*/
61 void *event_userdata; /**< DVR record event userdata*/
pengfei.liuab5a2262020-02-14 17:33:40 +080062 //DVR_VodContext_t vod; /**< DVR record vod context*/
63 int is_vod; /**< Indicate current mode is VOD record mode*/
pengfei.liu27cc4ec2020-04-03 16:28:16 +080064 DVR_CryptoFunction_t enc_func; /**< Encrypt function*/
pengfei.liu07ddc8a2020-03-24 23:36:53 +080065 void *enc_userdata; /**< Encrypt userdata*/
66 int is_secure_mode; /**< Record session run in secure pipeline */
hualing chen2615aa82020-04-02 21:32:51 +080067 size_t last_send_size; /**< Last send notify segment size */
pengfei.liufda2a972020-04-09 14:47:15 +080068 uint32_t block_size; /**< DVR record block size */
hualing chenf9867402020-09-23 17:06:20 +080069 DVR_Bool_t is_new_dmx; /**< DVR is used new dmx driver */
hualing chen40accc32021-04-21 15:58:09 +080070 int index_type; /**< DVR is used pcr or local time */
Pengfei Liuc181a982020-01-07 19:27:13 +080071} DVR_RecordContext_t;
72
Gong Ke2a0ebbe2021-05-25 15:22:50 +080073extern ssize_t record_device_read_ext(Record_DeviceHandle_t handle, size_t *buf, size_t *len);
74
Pengfei Liuc181a982020-01-07 19:27:13 +080075static DVR_RecordContext_t record_ctx[MAX_DVR_RECORD_SESSION_COUNT] = {
76 {
Pengfei Liub4734232020-01-17 18:25:10 +080077 .state = DVR_RECORD_STATE_CLOSED
Pengfei Liuc181a982020-01-07 19:27:13 +080078 },
79 {
Pengfei Liub4734232020-01-17 18:25:10 +080080 .state = DVR_RECORD_STATE_CLOSED
Pengfei Liuc181a982020-01-07 19:27:13 +080081 }
82};
83
Zhiqiang Han51646a02020-04-05 18:43:22 +080084static int record_is_valid_pid(DVR_RecordContext_t *p_ctx, int pid)
85{
86 int i;
87
88 for (i = 0; i < p_ctx->segment_info.nb_pids; i++) {
89 if (pid == p_ctx->segment_info.pids[i].pid)
90 return 1;
91 }
92 return 0;
93}
94
pengfei.liuab5a2262020-02-14 17:33:40 +080095static int record_save_pcr(DVR_RecordContext_t *p_ctx, uint8_t *buf, loff_t pos)
96{
97 uint8_t *p = buf;
98 int len;
99 uint8_t afc;
100 uint64_t pcr = 0;
101 int has_pcr = 0;
102 int pid;
103 int adp_field_len;
104
105 pid = ((p[1] & 0x1f) << 8) | p[2];
Zhiqiang Han51646a02020-04-05 18:43:22 +0800106 if (pid == 0x1fff || !record_is_valid_pid(p_ctx, pid))
pengfei.liuab5a2262020-02-14 17:33:40 +0800107 return has_pcr;
108
109 //scramble = p[3] >> 6;
110 //cc = p[3] & 0x0f;
111 afc = (p[3] >> 4) & 0x03;
112
113 p += 4;
114 len = 184;
115
116 if (afc & 2) {
117 adp_field_len = p[0];
118 /* Skip adaptation len */
119 p++;
120 len--;
121 /* Parse pcr field, see 13818 spec table I-2-6,adaptation_field */
hualing chen5605eed2020-05-26 18:18:06 +0800122 if (p[0] & 0x10 && len >= 6 && adp_field_len >= 6) {
pengfei.liuab5a2262020-02-14 17:33:40 +0800123 /* get pcr value,pcr is 33bit value */
124 pcr = (((uint64_t)(p[1])) << 25)
125 | (((uint64_t)p[2]) << 17)
126 | (((uint64_t)(p[3])) << 9)
127 | (((uint64_t)p[4]) << 1)
128 | ((((uint64_t)p[5]) & 0x80) >> 7);
129 has_pcr = 1;
130 }
131
132 p += adp_field_len;
133 len -= adp_field_len;
134
135 if (len < 0) {
136 DVR_DEBUG(1, "parser pcr: illegal adaptation field length");
137 return 0;
138 }
139 }
140
hualing chen40accc32021-04-21 15:58:09 +0800141 if (has_pcr && p_ctx->index_type == DVR_INDEX_TYPE_PCR) {
pengfei.liuab5a2262020-02-14 17:33:40 +0800142 segment_update_pts(p_ctx->segment_handle, pcr/90, pos);
143 }
144 return has_pcr;
145}
146
147static int record_do_pcr_index(DVR_RecordContext_t *p_ctx, uint8_t *buf, int len)
148{
149 uint8_t *p = buf;
150 int left = len;
151 loff_t pos;
152 int has_pcr = 0;
153
154 pos = segment_tell_position(p_ctx->segment_handle);
155 while (left >= 188) {
156 if (*p == 0x47) {
157 has_pcr |= record_save_pcr(p_ctx, p, pos);
158 p += 188;
159 left -= 188;
160 pos += 188;
161 } else {
162 p++;
163 left --;
164 pos++;
165 }
166 }
167 return has_pcr;
168}
169
pengfei.liu567d6d82020-04-17 16:48:59 +0800170static int get_diff_time(struct timeval start_tv, struct timeval end_tv)
171{
172 return end_tv.tv_sec * 1000 + end_tv.tv_usec / 1000 - start_tv.tv_sec * 1000 - start_tv.tv_usec / 1000;
173}
174
Pengfei Liuc181a982020-01-07 19:27:13 +0800175void *record_thread(void *arg)
176{
177 DVR_RecordContext_t *p_ctx = (DVR_RecordContext_t *)arg;
178 ssize_t len;
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800179 uint8_t *buf, *buf_out;
pengfei.liufda2a972020-04-09 14:47:15 +0800180 uint32_t block_size = p_ctx->block_size;
pengfei.liuab5a2262020-02-14 17:33:40 +0800181 loff_t pos = 0;
Pengfei Liuc181a982020-01-07 19:27:13 +0800182 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800183 struct timespec start_ts, end_ts;
184 DVR_RecordStatus_t record_status;
pengfei.liuab5a2262020-02-14 17:33:40 +0800185 int has_pcr;
hualing chen40accc32021-04-21 15:58:09 +0800186
hualing chen87072a82020-03-12 16:20:12 +0800187 time_t pre_time = 0;
hualing chen2932d372020-04-29 13:44:00 +0800188 #define DVR_STORE_INFO_TIME (400)
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800189 DVR_SecureBuffer_t secure_buf;
hualing chenf9867402020-09-23 17:06:20 +0800190 DVR_NewDmxSecureBuffer_t new_dmx_secure_buf;
hualing chend241c7a2021-06-22 13:34:27 +0800191
192 if (CONTROL_SPEED_ENABLE == 0)
193 p_ctx->index_type = DVR_INDEX_TYPE_INVALID;
194 else
195 p_ctx->index_type = DVR_INDEX_TYPE_LOCAL_CLOCK;
Pengfei Liuc181a982020-01-07 19:27:13 +0800196
Pengfei Liub4734232020-01-17 18:25:10 +0800197 buf = (uint8_t *)malloc(block_size);
Pengfei Liuc181a982020-01-07 19:27:13 +0800198 if (!buf) {
199 DVR_DEBUG(1, "%s, malloc failed", __func__);
200 return NULL;
201 }
202
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800203 buf_out = (uint8_t *)malloc(block_size + 188);
204 if (!buf_out) {
205 DVR_DEBUG(1, "%s, malloc failed", __func__);
Pengfei Liufaf38e42020-05-22 00:28:02 +0800206 free(buf);
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800207 return NULL;
208 }
209
hualing chen266b9502020-04-04 17:39:39 +0800210 memset(&record_status, 0, sizeof(record_status));
211 record_status.state = DVR_RECORD_STATE_STARTED;
pengfei.liufda2a972020-04-09 14:47:15 +0800212 if (p_ctx->event_notify_fn) {
hualing chen4b7c15d2020-04-07 16:13:48 +0800213 record_status.info.id = p_ctx->segment_info.id;
pengfei.liufda2a972020-04-09 14:47:15 +0800214 p_ctx->event_notify_fn(DVR_RECORD_EVENT_STATUS, &record_status, p_ctx->event_userdata);
hualing chen4b7c15d2020-04-07 16:13:48 +0800215 DVR_DEBUG(1, "%s line %d notify record status, state:%d id=%lld",
216 __func__,__LINE__, record_status.state, p_ctx->segment_info.id);
pengfei.liufda2a972020-04-09 14:47:15 +0800217 }
218 DVR_DEBUG(1, "%s, secure_mode:%d, block_size:%d", __func__, p_ctx->is_secure_mode, block_size);
Pengfei Liub4734232020-01-17 18:25:10 +0800219 clock_gettime(CLOCK_MONOTONIC, &start_ts);
pengfei.liu567d6d82020-04-17 16:48:59 +0800220
221 struct timeval t1, t2, t3, t4, t5, t6, t7;
hualing chen03fd4942021-07-15 15:56:41 +0800222 while (p_ctx->state == DVR_RECORD_STATE_STARTED ||
223 p_ctx->state == DVR_RECORD_STATE_PAUSE) {
224
225 if (p_ctx->state == DVR_RECORD_STATE_PAUSE) {
226 //wait resume record
227 usleep(20*1000);
228 continue;
229 }
pengfei.liu567d6d82020-04-17 16:48:59 +0800230 gettimeofday(&t1, NULL);
hualing chenc70a8df2020-05-12 19:23:11 +0800231
pengfei.liuab5a2262020-02-14 17:33:40 +0800232 /* data from dmx, normal dvr case */
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800233 if (p_ctx->is_secure_mode) {
hualing chenf9867402020-09-23 17:06:20 +0800234 if (p_ctx->is_new_dmx) {
Yahui Hance15e9c2020-12-08 18:08:32 +0800235
236 /* We resolve the below invoke for dvbcore to be under safety status */
hualing chenf9867402020-09-23 17:06:20 +0800237 memset(&new_dmx_secure_buf, 0, sizeof(new_dmx_secure_buf));
Yahui Hance15e9c2020-12-08 18:08:32 +0800238 len = record_device_read(p_ctx->dev_handle, &new_dmx_secure_buf, sizeof(new_dmx_secure_buf), 10);
239 if (len == DVR_FAILURE) {
Gong Ke2a0ebbe2021-05-25 15:22:50 +0800240 DVR_DEBUG(1, "handle[%p] ret:%d\n", p_ctx->dev_handle, ret);
Yahui Hance15e9c2020-12-08 18:08:32 +0800241 /*For the second recording, poll always failed which we should check
242 * dvbcore further. For now, Just ignore the fack poll fail, I think
243 * it won't influce anything. But we need adjust the poll timeout
244 * from 1000ms to 10ms.
245 */
246 //continue;
247 }
248
249 /* Read data from secure demux TA */
250 len = record_device_read_ext(p_ctx->dev_handle, &secure_buf.addr,
251 &secure_buf.len);
252
hualing chenf9867402020-09-23 17:06:20 +0800253 } else {
254 memset(&secure_buf, 0, sizeof(secure_buf));
255 len = record_device_read(p_ctx->dev_handle, &secure_buf, sizeof(secure_buf), 1000);
256 }
257 if (len != DVR_FAILURE) {
hualing chen4fe3bee2020-10-23 13:58:52 +0800258 //DVR_DEBUG(1, "%s, secure_buf:%#x, size:%#x", __func__, secure_buf.addr, secure_buf.len);
hualing chenf9867402020-09-23 17:06:20 +0800259 }
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800260 } else {
261 len = record_device_read(p_ctx->dev_handle, buf, block_size, 1000);
262 }
Pengfei Liub4734232020-01-17 18:25:10 +0800263 if (len == DVR_FAILURE) {
hualing chen6c126382020-04-13 15:47:51 +0800264 //usleep(10*1000);
hualing chen2932d372020-04-29 13:44:00 +0800265 DVR_DEBUG(1, "%s, start_read error", __func__);
Pengfei Liub4734232020-01-17 18:25:10 +0800266 continue;
267 }
pengfei.liu567d6d82020-04-17 16:48:59 +0800268 gettimeofday(&t2, NULL);
hualing chenc70a8df2020-05-12 19:23:11 +0800269
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800270 /* Got data from device, record it */
271 if (p_ctx->enc_func) {
272 /* Encrypt record data */
pengfei.liu27cc4ec2020-04-03 16:28:16 +0800273 DVR_CryptoParams_t crypto_params;
274
275 memset(&crypto_params, 0, sizeof(crypto_params));
276 crypto_params.type = DVR_CRYPTO_TYPE_ENCRYPT;
hualing chen7a56cba2020-04-14 14:09:27 +0800277 memcpy(crypto_params.location, p_ctx->location, sizeof(p_ctx->location));
pengfei.liu27cc4ec2020-04-03 16:28:16 +0800278 crypto_params.segment_id = p_ctx->segment_info.id;
279 crypto_params.offset = p_ctx->segment_info.size;
280
281 if (p_ctx->is_secure_mode) {
282 crypto_params.input_buffer.type = DVR_BUFFER_TYPE_SECURE;
Yahui Hance15e9c2020-12-08 18:08:32 +0800283#if 0
hualing chenf9867402020-09-23 17:06:20 +0800284 if (p_ctx->is_new_dmx) {
285 crypto_params.input_buffer.addr = new_dmx_secure_buf.data_start;
286 crypto_params.input_buffer.size = new_dmx_secure_buf.data_end - new_dmx_secure_buf.data_start;
Yahui Hance15e9c2020-12-08 18:08:32 +0800287 } else
288#endif
289 {
hualing chenf9867402020-09-23 17:06:20 +0800290 crypto_params.input_buffer.addr = secure_buf.addr;
291 crypto_params.input_buffer.size = secure_buf.len;
292 }
pengfei.liu27cc4ec2020-04-03 16:28:16 +0800293 } else {
294 crypto_params.input_buffer.type = DVR_BUFFER_TYPE_NORMAL;
295 crypto_params.input_buffer.addr = (size_t)buf;
296 crypto_params.input_buffer.size = len;
297 }
298
299 crypto_params.output_buffer.type = DVR_BUFFER_TYPE_NORMAL;
300 crypto_params.output_buffer.addr = (size_t)buf_out;
301 crypto_params.output_buffer.size = block_size + 188;
hualing chen9811b212020-10-29 11:21:44 +0800302
pengfei.liu27cc4ec2020-04-03 16:28:16 +0800303 p_ctx->enc_func(&crypto_params, p_ctx->enc_userdata);
pengfei.liu567d6d82020-04-17 16:48:59 +0800304 gettimeofday(&t3, NULL);
pengfei.liu27cc4ec2020-04-03 16:28:16 +0800305 /* Out buffer length may not equal in buffer length */
hualing chenf9867402020-09-23 17:06:20 +0800306 if (crypto_params.output_size > 0) {
307 ret = segment_write(p_ctx->segment_handle, buf_out, crypto_params.output_size);
308 len = crypto_params.output_size;
hualing chenbafc62d2020-11-02 15:44:05 +0800309 } else {
310 len = 0;
hualing chenf9867402020-09-23 17:06:20 +0800311 }
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800312 } else {
pengfei.liu567d6d82020-04-17 16:48:59 +0800313 gettimeofday(&t3, NULL);
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800314 ret = segment_write(p_ctx->segment_handle, buf, len);
315 }
pengfei.liu567d6d82020-04-17 16:48:59 +0800316 gettimeofday(&t4, NULL);
hualing chen626204e2020-04-07 11:55:08 +0800317 //add DVR_RECORD_EVENT_WRITE_ERROR event if write error
pengfei.liufda2a972020-04-09 14:47:15 +0800318 if (ret == -1 && len > 0 && p_ctx->event_notify_fn) {
hualing chen626204e2020-04-07 11:55:08 +0800319 //send write event
hualing chen9b434f02020-06-10 15:06:54 +0800320 if (p_ctx->event_notify_fn) {
hualing chen4b7c15d2020-04-07 16:13:48 +0800321 memset(&record_status, 0, sizeof(record_status));
hualing chen4fe3bee2020-10-23 13:58:52 +0800322 DVR_DEBUG(1, "%s:%d,send event write error", __func__,__LINE__);
hualing chen9ce7d942021-06-30 13:31:01 +0800323 record_status.info.id = p_ctx->segment_info.id;
hualing chen4b7c15d2020-04-07 16:13:48 +0800324 p_ctx->event_notify_fn(DVR_RECORD_EVENT_WRITE_ERROR, &record_status, p_ctx->event_userdata);
325 }
hualing chenc70a8df2020-05-12 19:23:11 +0800326 DVR_DEBUG(1, "%s,write error %d", __func__,__LINE__);
hualing chen626204e2020-04-07 11:55:08 +0800327 goto end;
328 }
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800329 /* Do time index */
330 uint8_t *index_buf = p_ctx->enc_func ? buf_out : buf;
pengfei.liuab5a2262020-02-14 17:33:40 +0800331 pos = segment_tell_position(p_ctx->segment_handle);
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800332 has_pcr = record_do_pcr_index(p_ctx, index_buf, len);
hualing chen40accc32021-04-21 15:58:09 +0800333 if (has_pcr == 0 && p_ctx->index_type == DVR_INDEX_TYPE_INVALID) {
pengfei.liuab5a2262020-02-14 17:33:40 +0800334 clock_gettime(CLOCK_MONOTONIC, &end_ts);
335 if ((end_ts.tv_sec*1000 + end_ts.tv_nsec/1000000) -
336 (start_ts.tv_sec*1000 + start_ts.tv_nsec/1000000) > 40) {
337 /* PCR interval threshlod > 40 ms*/
338 DVR_DEBUG(1, "%s use local clock time index", __func__);
hualing chen40accc32021-04-21 15:58:09 +0800339 p_ctx->index_type = DVR_INDEX_TYPE_LOCAL_CLOCK;
pengfei.liuab5a2262020-02-14 17:33:40 +0800340 }
hualing chen40accc32021-04-21 15:58:09 +0800341 } else if (has_pcr && p_ctx->index_type == DVR_INDEX_TYPE_INVALID){
pengfei.liuab5a2262020-02-14 17:33:40 +0800342 DVR_DEBUG(1, "%s use pcr time index", __func__);
hualing chen40accc32021-04-21 15:58:09 +0800343 p_ctx->index_type = DVR_INDEX_TYPE_PCR;
Pengfei Liuc181a982020-01-07 19:27:13 +0800344 }
pengfei.liu567d6d82020-04-17 16:48:59 +0800345 gettimeofday(&t5, NULL);
pengfei.liuab5a2262020-02-14 17:33:40 +0800346
347 /* Update segment info */
Pengfei Liub4734232020-01-17 18:25:10 +0800348 p_ctx->segment_info.size += len;
pengfei.liuab5a2262020-02-14 17:33:40 +0800349 /*Duration need use pcr to calculate, todo...*/
hualing chen40accc32021-04-21 15:58:09 +0800350 if (p_ctx->index_type == DVR_INDEX_TYPE_PCR) {
pengfei.liu8b563292020-02-26 15:49:02 +0800351 p_ctx->segment_info.duration = segment_tell_total_time(p_ctx->segment_handle);
hualing chen87072a82020-03-12 16:20:12 +0800352 if (pre_time == 0)
353 pre_time = p_ctx->segment_info.duration;
hualing chen40accc32021-04-21 15:58:09 +0800354 } else if (p_ctx->index_type == DVR_INDEX_TYPE_LOCAL_CLOCK) {
pengfei.liuab5a2262020-02-14 17:33:40 +0800355 clock_gettime(CLOCK_MONOTONIC, &end_ts);
356 p_ctx->segment_info.duration = (end_ts.tv_sec*1000 + end_ts.tv_nsec/1000000) -
357 (start_ts.tv_sec*1000 + start_ts.tv_nsec/1000000);
hualing chen87072a82020-03-12 16:20:12 +0800358 if (pre_time == 0)
359 pre_time = p_ctx->segment_info.duration;
pengfei.liuab5a2262020-02-14 17:33:40 +0800360 segment_update_pts(p_ctx->segment_handle, p_ctx->segment_info.duration, pos);
361 } else {
362 DVR_DEBUG(1, "%s can NOT do time index", __func__);
363 }
364 p_ctx->segment_info.nb_packets = p_ctx->segment_info.size/188;
Pengfei Liub4734232020-01-17 18:25:10 +0800365
hualing chen87072a82020-03-12 16:20:12 +0800366 if (p_ctx->segment_info.duration - pre_time > DVR_STORE_INFO_TIME) {
367 pre_time = p_ctx->segment_info.duration + DVR_STORE_INFO_TIME;
hualing chenf9867402020-09-23 17:06:20 +0800368 segment_store_info(p_ctx->segment_handle, &(p_ctx->segment_info));
hualing chen87072a82020-03-12 16:20:12 +0800369 }
pengfei.liu567d6d82020-04-17 16:48:59 +0800370 gettimeofday(&t6, NULL);
hualing chen87072a82020-03-12 16:20:12 +0800371 /*Event notification*/
Pengfei Liub4734232020-01-17 18:25:10 +0800372 if (p_ctx->notification_size &&
373 p_ctx->event_notify_fn &&
hualing chen2615aa82020-04-02 21:32:51 +0800374 /*!(p_ctx->segment_info.size % p_ctx->notification_size)*/
375 (p_ctx->segment_info.size -p_ctx->last_send_size) >= p_ctx->notification_size&&
pengfei.liuab5a2262020-02-14 17:33:40 +0800376 p_ctx->segment_info.duration > 0) {
Pengfei Liub4734232020-01-17 18:25:10 +0800377 memset(&record_status, 0, sizeof(record_status));
pengfei.liuab5a2262020-02-14 17:33:40 +0800378 //clock_gettime(CLOCK_MONOTONIC, &end_ts);
hualing chen2615aa82020-04-02 21:32:51 +0800379 p_ctx->last_send_size = p_ctx->segment_info.size;
Pengfei Liub4734232020-01-17 18:25:10 +0800380 record_status.state = p_ctx->state;
381 record_status.info.id = p_ctx->segment_info.id;
pengfei.liuab5a2262020-02-14 17:33:40 +0800382 record_status.info.duration = p_ctx->segment_info.duration;
Pengfei Liub4734232020-01-17 18:25:10 +0800383 record_status.info.size = p_ctx->segment_info.size;
384 record_status.info.nb_packets = p_ctx->segment_info.size/188;
385 p_ctx->event_notify_fn(DVR_RECORD_EVENT_STATUS, &record_status, p_ctx->event_userdata);
hualing chen4fe3bee2020-10-23 13:58:52 +0800386 DVR_DEBUG(1, "%s notify record status, state:%d, id:%lld, duration:%ld ms, size:%zu loc[%s]",
387 __func__, record_status.state,
388 record_status.info.id, record_status.info.duration,
389 record_status.info.size, p_ctx->location);
Pengfei Liub4734232020-01-17 18:25:10 +0800390 }
pengfei.liu567d6d82020-04-17 16:48:59 +0800391 gettimeofday(&t7, NULL);
392#ifdef DEBUG_PERFORMANCE
hualing chen2932d372020-04-29 13:44:00 +0800393 DVR_DEBUG(1, "record count, read:%dms, encrypt:%dms, write:%dms, index:%dms, store:%dms, notify:%dms total:%dms read len:%zd ",
pengfei.liu567d6d82020-04-17 16:48:59 +0800394 get_diff_time(t1, t2), get_diff_time(t2, t3), get_diff_time(t3, t4), get_diff_time(t4, t5),
hualing chen2932d372020-04-29 13:44:00 +0800395 get_diff_time(t5, t6), get_diff_time(t6, t7), get_diff_time(t1, t5), len);
pengfei.liu567d6d82020-04-17 16:48:59 +0800396#endif
Pengfei Liuc181a982020-01-07 19:27:13 +0800397 }
hualing chen626204e2020-04-07 11:55:08 +0800398end:
Pengfei Liub4734232020-01-17 18:25:10 +0800399 free((void *)buf);
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800400 free((void *)buf_out);
Pengfei Liub4734232020-01-17 18:25:10 +0800401 DVR_DEBUG(1, "exit %s", __func__);
Pengfei Liuc181a982020-01-07 19:27:13 +0800402 return NULL;
403}
404
405int dvr_record_open(DVR_RecordHandle_t *p_handle, DVR_RecordOpenParams_t *params)
406{
407 DVR_RecordContext_t *p_ctx;
408 Record_DeviceOpenParams_t dev_open_params;
409 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800410 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800411
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800412 DVR_RETURN_IF_FALSE(p_handle);
413 DVR_RETURN_IF_FALSE(params);
Pengfei Liuc181a982020-01-07 19:27:13 +0800414
415 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
Pengfei Liub4734232020-01-17 18:25:10 +0800416 if (record_ctx[i].state == DVR_RECORD_STATE_CLOSED) {
Pengfei Liuc181a982020-01-07 19:27:13 +0800417 break;
418 }
419 }
Pengfei Liufaf38e42020-05-22 00:28:02 +0800420 DVR_RETURN_IF_FALSE(i < MAX_DVR_RECORD_SESSION_COUNT);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800421 DVR_RETURN_IF_FALSE(record_ctx[i].state == DVR_RECORD_STATE_CLOSED);
Pengfei Liuc181a982020-01-07 19:27:13 +0800422 p_ctx = &record_ctx[i];
hualing chenfbf8e022020-06-15 13:43:11 +0800423 DVR_DEBUG(1, "%s , current state:%d, dmx_id:%d, notification_size:%zu ", __func__,
Pengfei Liub4734232020-01-17 18:25:10 +0800424 p_ctx->state, params->dmx_dev_id, params->notification_size);
Pengfei Liuc181a982020-01-07 19:27:13 +0800425
Pengfei Liub4734232020-01-17 18:25:10 +0800426 /*Process event params*/
427 p_ctx->notification_size = params->notification_size;
428 p_ctx->event_notify_fn = params->event_fn;
429 p_ctx->event_userdata = params->event_userdata;
hualing chen2615aa82020-04-02 21:32:51 +0800430 p_ctx->last_send_size = 0;
hualing chenf9867402020-09-23 17:06:20 +0800431 //check is new driver
432 p_ctx->is_new_dmx = dvr_check_dmx_isNew();
Pengfei Liub4734232020-01-17 18:25:10 +0800433 /*Process crypto params, todo*/
Pengfei Liub4734232020-01-17 18:25:10 +0800434 memset((void *)&dev_open_params, 0, sizeof(dev_open_params));
pengfei.liuab5a2262020-02-14 17:33:40 +0800435 if (params->data_from_memory) {
436 /* data from memory, VOD case */
437 p_ctx->is_vod = 1;
438 } else {
439 p_ctx->is_vod = 0;
440 /* data from dmx, normal dvr case */
hualing chen958fe4c2020-03-24 17:35:07 +0800441 dev_open_params.dmx_dev_id = params->dmx_dev_id;
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800442 dev_open_params.buf_size = (params->flush_size > 0 ? params->flush_size : RECORD_BLOCK_SIZE);
hualing chen03fd4942021-07-15 15:56:41 +0800443 dev_open_params.ringbuf_size = params->ringbuf_size;
hualing chen9811b212020-10-29 11:21:44 +0800444 if (p_ctx->is_new_dmx)
hualing cheneceb37e2021-01-18 16:07:48 +0800445 dev_open_params.buf_size = NEW_DEVICE_RECORD_BLOCK_SIZE * 30;
pengfei.liuab5a2262020-02-14 17:33:40 +0800446 ret = record_device_open(&p_ctx->dev_handle, &dev_open_params);
447 if (ret != DVR_SUCCESS) {
448 DVR_DEBUG(1, "%s, open record devices failed", __func__);
449 return DVR_FAILURE;
450 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800451 }
452
pengfei.liufda2a972020-04-09 14:47:15 +0800453 p_ctx->block_size = (params->flush_size > 0 ? params->flush_size : RECORD_BLOCK_SIZE);
hualing chen9811b212020-10-29 11:21:44 +0800454 if (p_ctx->is_new_dmx)
Yahui Hance15e9c2020-12-08 18:08:32 +0800455 p_ctx->block_size = NEW_DEVICE_RECORD_BLOCK_SIZE * 30;
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800456 p_ctx->enc_func = NULL;
457 p_ctx->enc_userdata = NULL;
458 p_ctx->is_secure_mode = 0;
Pengfei Liuc181a982020-01-07 19:27:13 +0800459 p_ctx->state = DVR_RECORD_STATE_OPENED;
hualing chen9811b212020-10-29 11:21:44 +0800460 DVR_DEBUG(1, "%s, block_size:%d is_new:%d", __func__, p_ctx->block_size, p_ctx->is_new_dmx);
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800461 *p_handle = p_ctx;
Pengfei Liuc181a982020-01-07 19:27:13 +0800462 return DVR_SUCCESS;
463}
464
465int dvr_record_close(DVR_RecordHandle_t handle)
466{
467 DVR_RecordContext_t *p_ctx;
468 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800469 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800470
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800471 p_ctx = (DVR_RecordContext_t *)handle;
472 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
473 if (p_ctx == &record_ctx[i])
474 break;
475 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800476 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800477
Pengfei Liub4734232020-01-17 18:25:10 +0800478 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800479 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
Pengfei Liuc181a982020-01-07 19:27:13 +0800480
pengfei.liuab5a2262020-02-14 17:33:40 +0800481 if (p_ctx->is_vod) {
482 ret = DVR_SUCCESS;
483 } else {
484 ret = record_device_close(p_ctx->dev_handle);
485 if (ret != DVR_SUCCESS) {
486 DVR_DEBUG(1, "%s, failed", __func__);
487 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800488 }
489
Pengfei Liub4734232020-01-17 18:25:10 +0800490 p_ctx->state = DVR_RECORD_STATE_CLOSED;
Pengfei Liuc181a982020-01-07 19:27:13 +0800491 return ret;
492}
493
hualing chen03fd4942021-07-15 15:56:41 +0800494int dvr_record_pause(DVR_RecordHandle_t handle)
495{
496 DVR_RecordContext_t *p_ctx;
497 int ret;
498 uint32_t i;
499
500 p_ctx = (DVR_RecordContext_t *)handle;
501 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
502 if (p_ctx == &record_ctx[i])
503 break;
504 }
505 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
506
507 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
508 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
509
510 if (p_ctx->is_vod) {
511 ret = DVR_SUCCESS;
512 }
513 //set pause state,will not store ts into segment
514 p_ctx->state = DVR_RECORD_STATE_PAUSE;
515 return ret;
516}
517
518int dvr_record_resume(DVR_RecordHandle_t handle)
519{
520 DVR_RecordContext_t *p_ctx;
521 int ret;
522 uint32_t i;
523
524 p_ctx = (DVR_RecordContext_t *)handle;
525 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
526 if (p_ctx == &record_ctx[i])
527 break;
528 }
529 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
530
531 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
532 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
533
534 if (p_ctx->is_vod) {
535 ret = DVR_SUCCESS;
536 }
537 //set stated state,will resume store ts into segment
538 p_ctx->state = DVR_RECORD_STATE_STARTED;
539 return ret;
540}
541
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800542#if 0
Pengfei Liuc181a982020-01-07 19:27:13 +0800543int dvr_record_register_encryption(DVR_RecordHandle_t handle,
544 DVR_CryptoFunction_t cb,
545 DVR_CryptoParams_t params,
546 void *userdata)
547{
548 return DVR_SUCCESS;
549}
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800550#endif
Pengfei Liuc181a982020-01-07 19:27:13 +0800551
552int dvr_record_start_segment(DVR_RecordHandle_t handle, DVR_RecordStartParams_t *params)
553{
554 DVR_RecordContext_t *p_ctx;
555 Segment_OpenParams_t open_params;
556 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800557 uint32_t i;
Pengfei Liuc181a982020-01-07 19:27:13 +0800558
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800559 p_ctx = (DVR_RecordContext_t *)handle;
560 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
561 if (p_ctx == &record_ctx[i])
562 break;
563 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800564 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800565
hualing chen4fe3bee2020-10-23 13:58:52 +0800566 DVR_DEBUG(1, "%s , current state:%d pids:%d params->location:%s", __func__, p_ctx->state, params->segment.nb_pids, params->location);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800567 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_STARTED);
568 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
569 DVR_RETURN_IF_FALSE(params);
Pengfei Liuc181a982020-01-07 19:27:13 +0800570
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800571 DVR_RETURN_IF_FALSE(strlen((const char *)params->location) < DVR_MAX_LOCATION_SIZE);
Pengfei Liuc181a982020-01-07 19:27:13 +0800572 memset(&open_params, 0, sizeof(open_params));
hualing chen7a56cba2020-04-14 14:09:27 +0800573 memcpy(open_params.location, params->location, sizeof(params->location));
Pengfei Liuc181a982020-01-07 19:27:13 +0800574 open_params.segment_id = params->segment.segment_id;
575 open_params.mode = SEGMENT_MODE_WRITE;
576
577 ret = segment_open(&open_params, &p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800578 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800579
Pengfei Liub4734232020-01-17 18:25:10 +0800580 /*process params*/
Pengfei Liuc181a982020-01-07 19:27:13 +0800581 {
hualing chen7a56cba2020-04-14 14:09:27 +0800582 memcpy(p_ctx->location, params->location, sizeof(params->location));
Pengfei Liub4734232020-01-17 18:25:10 +0800583 //need all params??
Pengfei Liuc181a982020-01-07 19:27:13 +0800584 memcpy(&p_ctx->segment_params, &params->segment, sizeof(params->segment));
Pengfei Liub4734232020-01-17 18:25:10 +0800585 /*save current segment info*/
586 memset(&p_ctx->segment_info, 0, sizeof(p_ctx->segment_info));
587 p_ctx->segment_info.id = params->segment.segment_id;
588 p_ctx->segment_info.nb_pids = params->segment.nb_pids;
589 memcpy(p_ctx->segment_info.pids, params->segment.pids, params->segment.nb_pids*sizeof(DVR_StreamPid_t));
Pengfei Liuc181a982020-01-07 19:27:13 +0800590 }
591
pengfei.liuab5a2262020-02-14 17:33:40 +0800592 if (!p_ctx->is_vod) {
593 /* normal dvr case */
594 for (i = 0; i < params->segment.nb_pids; i++) {
595 ret = record_device_add_pid(p_ctx->dev_handle, params->segment.pids[i].pid);
596 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
597 }
598 ret = record_device_start(p_ctx->dev_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800599 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800600 }
601
Zhiqiang Han5ebad992020-04-28 18:19:59 +0800602 ret = segment_store_info(p_ctx->segment_handle, &p_ctx->segment_info);
603
Pengfei Liuc181a982020-01-07 19:27:13 +0800604 p_ctx->state = DVR_RECORD_STATE_STARTED;
pengfei.liuab5a2262020-02-14 17:33:40 +0800605 if (!p_ctx->is_vod)
606 pthread_create(&p_ctx->thread, NULL, record_thread, p_ctx);
Pengfei Liub4734232020-01-17 18:25:10 +0800607
Pengfei Liuc181a982020-01-07 19:27:13 +0800608 return DVR_SUCCESS;
609}
610
611int dvr_record_next_segment(DVR_RecordHandle_t handle, DVR_RecordStartParams_t *params, DVR_RecordSegmentInfo_t *p_info)
612{
613 DVR_RecordContext_t *p_ctx;
Pengfei Liub4734232020-01-17 18:25:10 +0800614 Segment_OpenParams_t open_params;
Pengfei Liuc181a982020-01-07 19:27:13 +0800615 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800616 uint32_t i;
hualing chen2932d372020-04-29 13:44:00 +0800617 loff_t pos;
Pengfei Liuc181a982020-01-07 19:27:13 +0800618
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800619 p_ctx = (DVR_RecordContext_t *)handle;
620 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
621 if (p_ctx == &record_ctx[i])
622 break;
623 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800624 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800625
hualing chen4fe3bee2020-10-23 13:58:52 +0800626 DVR_DEBUG(1, "%s , current state:%d p_ctx->location:%s", __func__, p_ctx->state, p_ctx->location);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800627 DVR_RETURN_IF_FALSE(p_ctx->state == DVR_RECORD_STATE_STARTED);
628 //DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
629 DVR_RETURN_IF_FALSE(params);
630 DVR_RETURN_IF_FALSE(p_info);
pengfei.liuab5a2262020-02-14 17:33:40 +0800631 DVR_RETURN_IF_FALSE(!p_ctx->is_vod);
Pengfei Liuc181a982020-01-07 19:27:13 +0800632
633 /*Stop the on going record segment*/
Pengfei Liub4734232020-01-17 18:25:10 +0800634 //ret = record_device_stop(p_ctx->dev_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800635 //DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800636 p_ctx->state = DVR_RECORD_STATE_STOPPED;
637 pthread_join(p_ctx->thread, NULL);
638
hualing chen2932d372020-04-29 13:44:00 +0800639 //add index file store
640 pos = segment_tell_position(p_ctx->segment_handle);
641 segment_update_pts_force(p_ctx->segment_handle, p_ctx->segment_info.duration, pos);
642
643 p_ctx->segment_info.duration = segment_tell_total_time(p_ctx->segment_handle);
Pengfei Liub4734232020-01-17 18:25:10 +0800644 /*Update segment info*/
645 memcpy(p_info, &p_ctx->segment_info, sizeof(p_ctx->segment_info));
646
647 ret = segment_store_info(p_ctx->segment_handle, p_info);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800648 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liuc181a982020-01-07 19:27:13 +0800649
hualing chena540a7e2020-03-27 16:44:05 +0800650 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",
651 __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 +0800652
Pengfei Liub4734232020-01-17 18:25:10 +0800653 /*Close current segment*/
654 ret = segment_close(p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800655 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800656 /*Open the new record segment*/
657 memset(&open_params, 0, sizeof(open_params));
hualing chen7a56cba2020-04-14 14:09:27 +0800658 memcpy(open_params.location, p_ctx->location, sizeof(p_ctx->location));
Pengfei Liub4734232020-01-17 18:25:10 +0800659 open_params.segment_id = params->segment.segment_id;
660 open_params.mode = SEGMENT_MODE_WRITE;
hualing chen7a56cba2020-04-14 14:09:27 +0800661 DVR_DEBUG(1, "%s: p_ctx->location:%s params->location:%s", __func__, p_ctx->location,params->location);
Pengfei Liub4734232020-01-17 18:25:10 +0800662
663 ret = segment_open(&open_params, &p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800664 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800665 /*process params*/
Pengfei Liuc181a982020-01-07 19:27:13 +0800666 {
Pengfei Liub4734232020-01-17 18:25:10 +0800667 //need all params??
Pengfei Liuc181a982020-01-07 19:27:13 +0800668 memcpy(&p_ctx->segment_params, &params->segment, sizeof(params->segment));
Pengfei Liub4734232020-01-17 18:25:10 +0800669 /*save current segment info*/
670 memset(&p_ctx->segment_info, 0, sizeof(p_ctx->segment_info));
671 p_ctx->segment_info.id = params->segment.segment_id;
672 memcpy(p_ctx->segment_info.pids, params->segment.pids, params->segment.nb_pids*sizeof(DVR_StreamPid_t));
Pengfei Liuc181a982020-01-07 19:27:13 +0800673 }
674
Pengfei Liub4734232020-01-17 18:25:10 +0800675 p_ctx->segment_info.nb_pids = 0;
Pengfei Liuc181a982020-01-07 19:27:13 +0800676 for (i = 0; i < params->segment.nb_pids; i++) {
Pengfei Liub4734232020-01-17 18:25:10 +0800677 switch (params->segment.pid_action[i]) {
678 case DVR_RECORD_PID_CREATE:
679 DVR_DEBUG(1, "%s create pid:%d", __func__, params->segment.pids[i].pid);
680 ret = record_device_add_pid(p_ctx->dev_handle, params->segment.pids[i].pid);
681 p_ctx->segment_info.nb_pids++;
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800682 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800683 break;
684 case DVR_RECORD_PID_KEEP:
685 DVR_DEBUG(1, "%s keep pid:%d", __func__, params->segment.pids[i].pid);
686 p_ctx->segment_info.nb_pids++;
687 break;
688 case DVR_RECORD_PID_CLOSE:
689 DVR_DEBUG(1, "%s close pid:%d", __func__, params->segment.pids[i].pid);
690 ret = record_device_remove_pid(p_ctx->dev_handle, params->segment.pids[i].pid);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800691 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800692 break;
693 default:
694 DVR_DEBUG(1, "%s wrong action pid:%d", __func__, params->segment.pids[i].pid);
695 return DVR_FAILURE;
696 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800697 }
698
Pengfei Liub4734232020-01-17 18:25:10 +0800699 //ret = record_device_start(p_ctx->dev_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800700 //DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
hualing chen4b7c15d2020-04-07 16:13:48 +0800701 /*Update segment info*/
702 ret = segment_store_info(p_ctx->segment_handle, &p_ctx->segment_info);
Pengfei Liuc181a982020-01-07 19:27:13 +0800703
Pengfei Liuc181a982020-01-07 19:27:13 +0800704 p_ctx->state = DVR_RECORD_STATE_STARTED;
Zhiqiang Han0d60f2b2020-05-26 14:39:54 +0800705 pthread_create(&p_ctx->thread, NULL, record_thread, p_ctx);
Pengfei Liuc181a982020-01-07 19:27:13 +0800706 return DVR_SUCCESS;
707}
708
709int dvr_record_stop_segment(DVR_RecordHandle_t handle, DVR_RecordSegmentInfo_t *p_info)
710{
711 DVR_RecordContext_t *p_ctx;
712 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800713 uint32_t i;
hualing chen2932d372020-04-29 13:44:00 +0800714 loff_t pos;
Pengfei Liuc181a982020-01-07 19:27:13 +0800715
Pengfei Liu47ed6c92020-01-17 11:23:41 +0800716 p_ctx = (DVR_RecordContext_t *)handle;
717 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
718 if (p_ctx == &record_ctx[i])
719 break;
720 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800721 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
Pengfei Liuc181a982020-01-07 19:27:13 +0800722
hualing chen4fe3bee2020-10-23 13:58:52 +0800723 DVR_DEBUG(1, "%s , current state:%d p_ctx->location:%s", __func__, p_ctx->state, p_ctx->location);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800724 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_STOPPED);
725 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
Zhiqiang Han2d8cd822020-03-16 13:58:10 +0800726 DVR_RETURN_IF_FALSE(p_info);/*should support NULL*/
Pengfei Liuc181a982020-01-07 19:27:13 +0800727
Pengfei Liuc181a982020-01-07 19:27:13 +0800728 p_ctx->state = DVR_RECORD_STATE_STOPPED;
pengfei.liuab5a2262020-02-14 17:33:40 +0800729 if (p_ctx->is_vod) {
pengfei.liu8b563292020-02-26 15:49:02 +0800730 p_ctx->segment_info.duration = segment_tell_total_time(p_ctx->segment_handle);
pengfei.liuab5a2262020-02-14 17:33:40 +0800731 p_ctx->segment_info.duration = 10*1000; //debug, should delete it
732 } else {
733 ret = record_device_stop(p_ctx->dev_handle);
Zhiqiang Han5c805cf2020-05-09 16:51:08 +0800734 //DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
735 if (ret != DVR_SUCCESS)
736 goto end;
pengfei.liuab5a2262020-02-14 17:33:40 +0800737 //p_ctx->state = DVR_RECORD_STATE_STOPPED;
738 pthread_join(p_ctx->thread, NULL);
739 }
740
hualing chen2932d372020-04-29 13:44:00 +0800741 //add index file store
742 pos = segment_tell_position(p_ctx->segment_handle);
743 segment_update_pts_force(p_ctx->segment_handle, p_ctx->segment_info.duration, pos);
hualing chene41f4372020-06-06 16:29:17 +0800744 p_ctx->segment_info.duration = segment_tell_total_time(p_ctx->segment_handle);
Pengfei Liuc181a982020-01-07 19:27:13 +0800745
Pengfei Liub4734232020-01-17 18:25:10 +0800746 /*Update segment info*/
747 memcpy(p_info, &p_ctx->segment_info, sizeof(p_ctx->segment_info));
748
749 ret = segment_store_info(p_ctx->segment_handle, p_info);
Zhiqiang Han5c805cf2020-05-09 16:51:08 +0800750 //DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
751 if (ret != DVR_SUCCESS)
752 goto end;
Pengfei Liub4734232020-01-17 18:25:10 +0800753
754 DVR_DEBUG(1, "%s dump segment info, id:%lld, nb_pids:%d, duration:%ld ms, size:%zu, nb_packets:%d",
755 __func__, p_info->id, p_info->nb_pids, p_info->duration, p_info->size, p_info->nb_packets);
756
Zhiqiang Han5c805cf2020-05-09 16:51:08 +0800757end:
Pengfei Liuc181a982020-01-07 19:27:13 +0800758 ret = segment_close(p_ctx->segment_handle);
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800759 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
Pengfei Liub4734232020-01-17 18:25:10 +0800760 return DVR_SUCCESS;
761}
Pengfei Liuc181a982020-01-07 19:27:13 +0800762
Pengfei Liub4734232020-01-17 18:25:10 +0800763int dvr_record_resume_segment(DVR_RecordHandle_t handle, DVR_RecordStartParams_t *params, uint64_t *p_resume_size)
764{
765 DVR_RecordContext_t *p_ctx;
766 uint32_t i;
pengfei.liuab5a2262020-02-14 17:33:40 +0800767 int ret;
Pengfei Liub4734232020-01-17 18:25:10 +0800768
769 p_ctx = (DVR_RecordContext_t *)handle;
770 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
771 if (p_ctx == &record_ctx[i])
772 break;
Pengfei Liuc181a982020-01-07 19:27:13 +0800773 }
Pengfei Liu3b1a8202020-02-12 23:04:21 +0800774 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
775 DVR_RETURN_IF_FALSE(params);
776 DVR_RETURN_IF_FALSE(p_resume_size);
Pengfei Liuc181a982020-01-07 19:27:13 +0800777
pengfei.liuab5a2262020-02-14 17:33:40 +0800778 DVR_DEBUG(1, "%s , current state:%d, resume size:%lld", __func__, p_ctx->state, *p_resume_size);
779 ret = dvr_record_start_segment(handle, params);
780 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
781
782 p_ctx->segment_info.size = *p_resume_size;
783
784 return DVR_SUCCESS;
785}
786
787int dvr_record_get_status(DVR_RecordHandle_t handle, DVR_RecordStatus_t *p_status)
788{
789 DVR_RecordContext_t *p_ctx;
790 int i;
791
792 p_ctx = (DVR_RecordContext_t *)handle;
793 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
794 if (p_ctx == &record_ctx[i])
795 break;
796 }
797 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
798 DVR_RETURN_IF_FALSE(p_status);
799
800 //lock
801 p_status->state = p_ctx->state;
802 p_status->info.id = p_ctx->segment_info.id;
803 p_status->info.duration = p_ctx->segment_info.duration;
804 p_status->info.size = p_ctx->segment_info.size;
805 p_status->info.nb_packets = p_ctx->segment_info.size/188;
806
807 return DVR_SUCCESS;
808}
809
810int dvr_record_write(DVR_RecordHandle_t handle, void *buffer, uint32_t len)
811{
812 DVR_RecordContext_t *p_ctx;
813 uint32_t i;
814 off_t pos = 0;
815 int ret;
816 int has_pcr;
817
818 p_ctx = (DVR_RecordContext_t *)handle;
819 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
820 if (p_ctx == &record_ctx[i])
821 break;
822 }
823 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
824 DVR_RETURN_IF_FALSE(buffer);
825 DVR_RETURN_IF_FALSE(len);
826
827 pos = segment_tell_position(p_ctx->segment_handle);
828 has_pcr = record_do_pcr_index(p_ctx, buffer, len);
829 if (has_pcr == 0) {
830 /* Pull VOD record shoud use PCR time index */
831 DVR_DEBUG(1, "%s has no pcr, can NOT do time index", __func__);
832 }
833 ret = segment_write(p_ctx->segment_handle, buffer, len);
hualing chen2932d372020-04-29 13:44:00 +0800834 if (ret != len) {
835 DVR_DEBUG(1, "%s write error ret:%d len:%d", __func__, ret, len);
836 }
pengfei.liuab5a2262020-02-14 17:33:40 +0800837 p_ctx->segment_info.size += len;
838 p_ctx->segment_info.nb_packets = p_ctx->segment_info.size/188;
839
Pengfei Liuc181a982020-01-07 19:27:13 +0800840 return DVR_SUCCESS;
841}
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800842
pengfei.liu27cc4ec2020-04-03 16:28:16 +0800843int dvr_record_set_encrypt_callback(DVR_RecordHandle_t handle, DVR_CryptoFunction_t func, void *userdata)
pengfei.liu07ddc8a2020-03-24 23:36:53 +0800844{
845 DVR_RecordContext_t *p_ctx;
846 uint32_t i;
847
848 p_ctx = (DVR_RecordContext_t *)handle;
849 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
850 if (p_ctx == &record_ctx[i])
851 break;
852 }
853 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
854 DVR_RETURN_IF_FALSE(func);
855
856 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
857 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_STARTED);
858 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
859
860 p_ctx->enc_func = func;
861 p_ctx->enc_userdata = userdata;
862 return DVR_SUCCESS;
863}
864
865int dvr_record_set_secure_buffer(DVR_RecordHandle_t handle, uint8_t *p_secure_buf, uint32_t len)
866{
867 DVR_RecordContext_t *p_ctx;
868 uint32_t i;
869 int ret;
870
871 p_ctx = (DVR_RecordContext_t *)handle;
872 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
873 if (p_ctx == &record_ctx[i])
874 break;
875 }
876 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
877 DVR_RETURN_IF_FALSE(p_secure_buf);
878 DVR_RETURN_IF_FALSE(len);
879
880 DVR_DEBUG(1, "%s , current state:%d", __func__, p_ctx->state);
881 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_STARTED);
882 DVR_RETURN_IF_FALSE(p_ctx->state != DVR_RECORD_STATE_CLOSED);
883
884 ret = record_device_set_secure_buffer(p_ctx->dev_handle, p_secure_buf, len);
885 DVR_RETURN_IF_FALSE(ret == DVR_SUCCESS);
886
887 p_ctx->is_secure_mode = 1;
888 return ret;
889}
hualing chen4fe3bee2020-10-23 13:58:52 +0800890
891int dvr_record_is_secure_mode(DVR_RecordHandle_t handle)
892{
893 DVR_RecordContext_t *p_ctx;
894 uint32_t i;
895 int ret;
896
897 p_ctx = (DVR_RecordContext_t *)handle;
898 for (i = 0; i < MAX_DVR_RECORD_SESSION_COUNT; i++) {
899 if (p_ctx == &record_ctx[i])
900 break;
901 }
902 DVR_RETURN_IF_FALSE(p_ctx == &record_ctx[i]);
903
904 if (p_ctx->is_secure_mode == 1)
905 ret = 1;
906 else
907 ret = 0;
908 return ret;
Yahui Hance15e9c2020-12-08 18:08:32 +0800909}