blob: fe534ac27629ae3a1a4733b216cef36f181b0e82 [file] [log] [blame]
Pengfei Liuc181a982020-01-07 19:27:13 +08001#include <stdio.h>
Pengfei Liub038b6a2020-01-14 15:57:01 +08002#include <unistd.h>
Pengfei Liuc181a982020-01-07 19:27:13 +08003#include <sys/types.h>
4#include <sys/stat.h>
5#include <fcntl.h>
6#include <string.h>
Pengfei Liub038b6a2020-01-14 15:57:01 +08007#include <stdlib.h>
Pengfei Liuc181a982020-01-07 19:27:13 +08008#include <errno.h>
Pengfei Liu47ed6c92020-01-17 11:23:41 +08009#include "dvr_types.h"
Pengfei Liuc181a982020-01-07 19:27:13 +080010#include "segment.h"
11
12#define MAX_SEGMENT_FD_COUNT (128)
13#define MAX_SEGMENT_PATH_SIZE (DVR_MAX_LOCATION_SIZE + 32)
Pengfei Liub038b6a2020-01-14 15:57:01 +080014#define MAX_PTS_THRESHOLD (10*1000)
Pengfei Liub4734232020-01-17 18:25:10 +080015/**\brief Segment context*/
Pengfei Liuc181a982020-01-07 19:27:13 +080016typedef struct {
Pengfei Liub4734232020-01-17 18:25:10 +080017 //char location[DVR_MAX_LOCATION_SIZE]; /**< Segment file location*/
18 //uint64_t segment_id; /**< Segment index*/
19 FILE *ts_fp; /**< Segment ts file fd*/
20 FILE *index_fp; /**< Time index file fd*/
21 FILE *dat_fp; /**< Information file fd*/
22 uint64_t first_pts; /**< First pts value, use for write mode*/
23 uint64_t last_pts; /**< Last pts value, use for write mode*/
Pengfei Liuc181a982020-01-07 19:27:13 +080024} Segment_Context_t;
25
Pengfei Liub4734232020-01-17 18:25:10 +080026/**\brief Segment file type*/
Pengfei Liuc181a982020-01-07 19:27:13 +080027typedef enum {
Pengfei Liub4734232020-01-17 18:25:10 +080028 SEGMENT_FILE_TYPE_TS, /**< Used for store TS data*/
29 SEGMENT_FILE_TYPE_INDEX, /**< Used for store index data*/
30 SEGMENT_FILE_TYPE_DAT, /**< Used for store information data, such as duration etc*/
Pengfei Liuc181a982020-01-07 19:27:13 +080031} Segment_FileType_t;
32
33static void segment_get_fname(char fname[MAX_SEGMENT_PATH_SIZE],
Pengfei Liub4734232020-01-17 18:25:10 +080034 const char location[DVR_MAX_LOCATION_SIZE],
Pengfei Liuc181a982020-01-07 19:27:13 +080035 uint64_t segment_id,
36 Segment_FileType_t type)
37{
38 int offset;
39
40 memset(fname, 0, MAX_SEGMENT_PATH_SIZE);
41 strncpy(fname, location, strlen(location));
42 offset = strlen(location);
43 strncpy(fname + offset, "-", 1);
44 offset += 1;
45 sprintf(fname + offset, "%04llu", segment_id);
46 offset += 4;
47 if (type == SEGMENT_FILE_TYPE_TS)
48 strncpy(fname + offset, ".ts", 3);
49 else if (type == SEGMENT_FILE_TYPE_INDEX)
50 strncpy(fname + offset, ".idx", 4);
Pengfei Liub4734232020-01-17 18:25:10 +080051 else if (type == SEGMENT_FILE_TYPE_DAT)
52 strncpy(fname + offset, ".dat", 4);
Pengfei Liuc181a982020-01-07 19:27:13 +080053}
54
55int segment_open(Segment_OpenParams_t *params, Segment_Handle_t *p_handle)
56{
57 Segment_Context_t *p_ctx;
58 char ts_fname[MAX_SEGMENT_PATH_SIZE];
59 char index_fname[MAX_SEGMENT_PATH_SIZE];
Pengfei Liub4734232020-01-17 18:25:10 +080060 char dat_fname[MAX_SEGMENT_PATH_SIZE];
Pengfei Liuc181a982020-01-07 19:27:13 +080061
62 DVR_ASSERT(params);
63 DVR_ASSERT(p_handle);
64
Pengfei Liub038b6a2020-01-14 15:57:01 +080065 DVR_DEBUG(1, "%s, location:%s, id:%llu", __func__, params->location, params->segment_id);
Pengfei Liuc181a982020-01-07 19:27:13 +080066
Pengfei Liub038b6a2020-01-14 15:57:01 +080067 p_ctx = (void*)malloc(sizeof(Segment_Context_t));
Pengfei Liuc181a982020-01-07 19:27:13 +080068 DVR_ASSERT(p_ctx);
Pengfei Liub4734232020-01-17 18:25:10 +080069 memset(p_ctx, 0, sizeof(Segment_Context_t));
Pengfei Liuc181a982020-01-07 19:27:13 +080070
71 memset(ts_fname, 0, sizeof(ts_fname));
72 segment_get_fname(ts_fname, params->location, params->segment_id, SEGMENT_FILE_TYPE_TS);
73
74 memset(index_fname, 0, sizeof(index_fname));
75 segment_get_fname(index_fname, params->location, params->segment_id, SEGMENT_FILE_TYPE_INDEX);
76
Pengfei Liub4734232020-01-17 18:25:10 +080077 memset(dat_fname, 0, sizeof(dat_fname));
78 segment_get_fname(dat_fname, params->location, params->segment_id, SEGMENT_FILE_TYPE_DAT);
79
Pengfei Liuc181a982020-01-07 19:27:13 +080080 if (params->mode == SEGMENT_MODE_READ) {
81 p_ctx->ts_fp = fopen(ts_fname, "r");
82 p_ctx->index_fp = fopen(index_fname, "r");
Pengfei Liub4734232020-01-17 18:25:10 +080083 p_ctx->dat_fp = fopen(dat_fname, "r");
Pengfei Liuc181a982020-01-07 19:27:13 +080084 } else if (params->mode == SEGMENT_MODE_WRITE) {
85 p_ctx->ts_fp = fopen(ts_fname, "w+");
86 p_ctx->index_fp = fopen(index_fname, "w+");
Pengfei Liub4734232020-01-17 18:25:10 +080087 p_ctx->dat_fp = fopen(dat_fname, "w+");
Pengfei Liub038b6a2020-01-14 15:57:01 +080088 p_ctx->first_pts = ULLONG_MAX;
89 p_ctx->last_pts = ULLONG_MAX;
Pengfei Liuc181a982020-01-07 19:27:13 +080090 } else {
91 DVR_DEBUG(1, "%s, unknow mode use default", __func__);
92 p_ctx->ts_fp = fopen(ts_fname, "r");
93 p_ctx->index_fp = fopen(index_fname, "r");
Pengfei Liub4734232020-01-17 18:25:10 +080094 p_ctx->dat_fp = fopen(dat_fname, "r");
Pengfei Liuc181a982020-01-07 19:27:13 +080095 }
96
Pengfei Liub4734232020-01-17 18:25:10 +080097 if (!p_ctx->ts_fp || !p_ctx->index_fp || !p_ctx->dat_fp) {
98 DVR_DEBUG(1, "%s open file failed [%s, %s, %s], reason:%s", __func__,
99 ts_fname, index_fname, dat_fname, strerror(errno));
Pengfei Liuc181a982020-01-07 19:27:13 +0800100 free(p_ctx);
Pengfei Liub038b6a2020-01-14 15:57:01 +0800101 *p_handle = NULL;
Pengfei Liuc181a982020-01-07 19:27:13 +0800102 return DVR_FAILURE;
103 }
Pengfei Liub4734232020-01-17 18:25:10 +0800104
105 DVR_DEBUG(1, "%s, open file success", __func__);
Pengfei Liub038b6a2020-01-14 15:57:01 +0800106 *p_handle = (Segment_Handle_t)p_ctx;
Pengfei Liuc181a982020-01-07 19:27:13 +0800107 return DVR_SUCCESS;
108}
109
110int segment_close(Segment_Handle_t handle)
111{
112 Segment_Context_t *p_ctx;
113
Pengfei Liub038b6a2020-01-14 15:57:01 +0800114 p_ctx = (void *)handle;
Pengfei Liuc181a982020-01-07 19:27:13 +0800115 DVR_ASSERT(p_ctx);
116
117 if (p_ctx->ts_fp) {
118 fclose(p_ctx->ts_fp);
119 }
120
121 if (p_ctx->index_fp) {
122 fclose(p_ctx->index_fp);
123 }
124
Pengfei Liub4734232020-01-17 18:25:10 +0800125 if (p_ctx->dat_fp) {
126 fclose(p_ctx->dat_fp);
127 }
128
Pengfei Liuc181a982020-01-07 19:27:13 +0800129 free(p_ctx);
130 return 0;
131}
132
133ssize_t segment_read(Segment_Handle_t handle, void *buf, size_t count)
134{
135 Segment_Context_t *p_ctx;
136
137 p_ctx = (Segment_Context_t *)handle;
138 DVR_ASSERT(p_ctx);
139 DVR_ASSERT(buf);
140 DVR_ASSERT(p_ctx->ts_fp);
141
Pengfei Liub038b6a2020-01-14 15:57:01 +0800142 return fread(buf, 1, count, p_ctx->ts_fp);
Pengfei Liuc181a982020-01-07 19:27:13 +0800143}
144
145ssize_t segment_write(Segment_Handle_t handle, void *buf, size_t count)
146{
147 Segment_Context_t *p_ctx;
148
149 p_ctx = (Segment_Context_t *)handle;
150 DVR_ASSERT(p_ctx);
151 DVR_ASSERT(buf);
152 DVR_ASSERT(p_ctx->ts_fp);
153
Pengfei Liub038b6a2020-01-14 15:57:01 +0800154 return fwrite(buf, 1, count, p_ctx->ts_fp);
Pengfei Liuc181a982020-01-07 19:27:13 +0800155}
156
157int segment_update_pts(Segment_Handle_t handle, uint64_t pts, off_t offset)
158{
159 Segment_Context_t *p_ctx;
160 char buf[256];
161
162 p_ctx = (Segment_Context_t *)handle;
163 DVR_ASSERT(p_ctx);
164 DVR_ASSERT(p_ctx->index_fp);
165
Pengfei Liub038b6a2020-01-14 15:57:01 +0800166 if (p_ctx->first_pts == ULLONG_MAX) {
167 p_ctx->first_pts = pts;
168 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800169 memset(buf, 0, sizeof(buf));
Pengfei Liub038b6a2020-01-14 15:57:01 +0800170 if (p_ctx->last_pts == ULLONG_MAX) {
171 /*Last pts is init value*/
172 sprintf(buf, "{time=%llu, offset=%ld}\n", pts - p_ctx->first_pts, offset);
173 } else {
174 /*Last pts has valid value*/
175 if (pts - p_ctx->last_pts > MAX_PTS_THRESHOLD) {
176 /*Current pts has a transition*/
177 sprintf(buf, "{time=%llu, offset=%ld}\n", p_ctx->last_pts - p_ctx->first_pts, offset);
178 } else {
179 /*This is a normal pts, record it*/
180 sprintf(buf, "{time=%llu, offset=%ld}\n", pts - p_ctx->first_pts, offset);
181 }
182 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800183
184 fputs(buf, p_ctx->index_fp);
Pengfei Liub038b6a2020-01-14 15:57:01 +0800185 p_ctx->last_pts = pts;
186 fflush(p_ctx->index_fp);
187 fsync(fileno(p_ctx->index_fp));
Pengfei Liub4734232020-01-17 18:25:10 +0800188
Pengfei Liuc181a982020-01-07 19:27:13 +0800189 return DVR_SUCCESS;
190}
191
192off_t segment_seek(Segment_Handle_t handle, uint64_t time)
193{
194 Segment_Context_t *p_ctx;
195 char buf[256];
196 char value[256];
197 uint64_t pts;
198 off_t offset;
199 char *p1, *p2;
200
201 p_ctx = (Segment_Context_t *)handle;
202 DVR_ASSERT(p_ctx);
203 DVR_ASSERT(p_ctx->index_fp);
204 DVR_ASSERT(p_ctx->ts_fp);
205
206 memset(buf, 0, sizeof(buf));
207 DVR_ASSERT(fseek(p_ctx->index_fp, 0, SEEK_SET) != -1);
208
209 while (fgets(buf, sizeof(buf), p_ctx->index_fp) != NULL) {
210 memset(value, 0, sizeof(value));
Pengfei Liub038b6a2020-01-14 15:57:01 +0800211 if ((p1 = strstr(buf, "time="))) {
Pengfei Liuc181a982020-01-07 19:27:13 +0800212 p1 += 4;
213 if ((p2 = strstr(buf, ","))) {
214 memcpy(value, p1, p2 - p1);
215 }
216 pts = strtoull(value, NULL, 10);
217 }
218
219 memset(value, 0, sizeof(value));
220 if ((p1 = strstr(buf, "offset="))) {
221 p1 += 7;
222 if ((p2 = strstr(buf, "}"))) {
223 memcpy(value, p1, p2 - p1);
224 }
225 offset = strtoull(value, NULL, 10);
226 }
227
228 memset(buf, 0, sizeof(buf));
Pengfei Liub038b6a2020-01-14 15:57:01 +0800229 DVR_DEBUG(1, "time=%llu, offset=%ld\n", pts, offset);
Pengfei Liuc181a982020-01-07 19:27:13 +0800230 if (time < pts) {
231 DVR_ASSERT(fseeko(p_ctx->ts_fp, offset, SEEK_SET) != -1);
232 return offset;
233 }
234 }
235
236 return DVR_FAILURE;
237}
238
239off_t segment_tell(Segment_Handle_t handle)
240{
241 Segment_Context_t *p_ctx;
242
243 p_ctx = (Segment_Context_t *)handle;
244 DVR_ASSERT(p_ctx);
245 DVR_ASSERT(p_ctx->ts_fp);
246
247 return ftello(p_ctx->ts_fp);
248}
Pengfei Liub038b6a2020-01-14 15:57:01 +0800249
Pengfei Liub4734232020-01-17 18:25:10 +0800250int segment_store_info(Segment_Handle_t handle, Segment_StoreInfo_t *p_info)
251{
252 Segment_Context_t *p_ctx;
253 char buf[256];
254 uint32_t i;
255
256 p_ctx = (Segment_Context_t *)handle;
257 DVR_ASSERT(p_ctx);
258 DVR_ASSERT(p_ctx->dat_fp);
259 DVR_ASSERT(p_info);
260
261 /*Save segment id*/
262 memset(buf, 0, sizeof(buf));
263 sprintf(buf, "id=%lld\n", p_info->id);
264 fputs(buf, p_ctx->dat_fp);
265
266 /*Save number of pids*/
267 memset(buf, 0, sizeof(buf));
268 sprintf(buf, "nb_pids=%d\n", p_info->nb_pids);
269 fputs(buf, p_ctx->dat_fp);
270
271 /*Save pid information*/
272 for (i = 0; i < p_info->nb_pids; i++) {
273 memset(buf, 0, sizeof(buf));
274 sprintf(buf, "{pid=%d, type=%d}\n", p_info->pids[i].pid, p_info->pids[i].type);
275 fputs(buf, p_ctx->dat_fp);
276 }
277
278 /*Save segment duration*/
279 memset(buf, 0, sizeof(buf));
280 sprintf(buf, "duration=%ld\n", p_info->duration);
281 fputs(buf, p_ctx->dat_fp);
282
283 /*Save segment size*/
284 memset(buf, 0, sizeof(buf));
285 sprintf(buf, "size=%zu\n", p_info->size);
286 fputs(buf, p_ctx->dat_fp);
287
288 /*Save number of packets*/
289 memset(buf, 0, sizeof(buf));
290 sprintf(buf, "nb_packets=%d\n", p_info->nb_packets);
291 fputs(buf, p_ctx->dat_fp);
292
293 fflush(p_ctx->dat_fp);
294 fsync(fileno(p_ctx->dat_fp));
295 return DVR_SUCCESS;
296}
297
298int segment_load_info(Segment_Handle_t handle, Segment_StoreInfo_t *p_info)
299{
300 Segment_Context_t *p_ctx;
301 uint32_t i;
302 char buf[256];
303 char value[256];
304 char *p1, *p2;
305
306 p_ctx = (Segment_Context_t *)handle;
307 DVR_ASSERT(p_ctx);
308 DVR_ASSERT(p_info);
309
310 /*Load segment id*/
311 p1 = fgets(buf, sizeof(buf), p_ctx->dat_fp);
312 DVR_ASSERT(p1);
313 p1 = strstr(buf, "id=");
314 p_info->id = strtoull(p1 + 3, NULL, 10);
315
316 /*Save number of pids*/
317 p1 = fgets(buf, sizeof(buf), p_ctx->dat_fp);
318 DVR_ASSERT(p1);
319 p1 = strstr(buf, "nb_pids=");
320 p_info->nb_pids = strtoull(p1 + 8, NULL, 10);
321
322 /*Save pid information*/
323 for (i = 0; i < p_info->nb_pids; i++) {
324 p1 = fgets(buf, sizeof(buf), p_ctx->dat_fp);
325 DVR_ASSERT(p1);
326 memset(value, 0, sizeof(value));
327 if ((p1 = strstr(buf, "pid="))) {
328 p1 += 4;
329 if ((p2 = strstr(buf, ","))) {
330 memcpy(value, p1, p2 - p1);
331 }
332 p_info->pids[i].pid = strtoull(value, NULL, 10);
333 }
334
335 memset(value, 0, sizeof(value));
336 if ((p1 = strstr(buf, "type="))) {
337 p1 += 5;
338 if ((p2 = strstr(buf, "}"))) {
339 memcpy(value, p1, p2 - p1);
340 }
341 p_info->pids[i].type = strtoull(value, NULL, 10);
342 }
343 }
344
345 /*Save segment duration*/
346 p1 = fgets(buf, sizeof(buf), p_ctx->dat_fp);
347 DVR_ASSERT(p1);
348 p1 = strstr(buf, "duration=");
349 p_info->duration = strtoull(p1 + 9, NULL, 10);
350
351 /*Save segment size*/
352 p1 = fgets(buf, sizeof(buf), p_ctx->dat_fp);
353 DVR_ASSERT(p1);
354 p1 = strstr(buf, "size=");
355 p_info->size = strtoull(p1 + 5, NULL, 10);
356
357 /*Save number of packets*/
358 p1 = fgets(buf, sizeof(buf), p_ctx->dat_fp);
359 DVR_ASSERT(p1);
360 p1 = strstr(buf, "nb_packets=");
361 p_info->nb_packets = strtoull(p1 + 11, NULL, 10);
362
363 return DVR_SUCCESS;
364}
365
366int segment_delete(const char *location, uint64_t segment_id)
367{
368 char fname[MAX_SEGMENT_PATH_SIZE];
369 int ret;
370
371 DVR_ASSERT(location);
372
373 /*delete ts file*/
374 memset(fname, 0, sizeof(fname));
375 segment_get_fname(fname, location, segment_id, SEGMENT_FILE_TYPE_TS);
376 ret = unlink(fname);
377 DVR_DEBUG(1, "%s, [%s] return:%s", __func__, fname, strerror(errno));
378 DVR_ASSERT(ret == 0);
379
380 /*delete index file*/
381 memset(fname, 0, sizeof(fname));
382 segment_get_fname(fname, location, segment_id, SEGMENT_FILE_TYPE_INDEX);
383 unlink(fname);
384 DVR_DEBUG(1, "%s, [%s] return:%s", __func__, fname, strerror(errno));
385 DVR_ASSERT(ret == 0);
386
387 /*delete store information file*/
388 memset(fname, 0, sizeof(fname));
389 segment_get_fname(fname, location, segment_id, SEGMENT_FILE_TYPE_DAT);
390 unlink(fname);
391 DVR_DEBUG(1, "%s, [%s] return:%s", __func__, fname, strerror(errno));
392 DVR_ASSERT(ret == 0);
393
394 return DVR_SUCCESS;
395}
396
Pengfei Liub038b6a2020-01-14 15:57:01 +0800397off_t segment_dump_pts(Segment_Handle_t handle)
398{
399 Segment_Context_t *p_ctx;
400 char buf[256];
401 char value[256];
402 uint64_t pts;
403 off_t offset;
404 char *p1, *p2;
405
406 p_ctx = (Segment_Context_t *)handle;
407 DVR_ASSERT(p_ctx);
408 DVR_ASSERT(p_ctx->index_fp);
409 DVR_ASSERT(p_ctx->ts_fp);
410
411 memset(buf, 0, sizeof(buf));
412 DVR_ASSERT(fseek(p_ctx->index_fp, 0, SEEK_SET) != -1);
413 printf("start gets pts\n");
414 while (fgets(buf, sizeof(buf), p_ctx->index_fp) != NULL) {
415 printf("buf[%s]\n", buf);
416 memset(value, 0, sizeof(value));
417 if ((p1 = strstr(buf, "time="))) {
418 p1 += 4;
419 if ((p2 = strstr(buf, ","))) {
420 memcpy(value, p1, p2 - p1);
421 }
422 pts = strtoull(value, NULL, 10);
423 }
424
425 memset(value, 0, sizeof(value));
426 if ((p1 = strstr(buf, "offset="))) {
427 p1 += 7;
428 if ((p2 = strstr(buf, "}"))) {
429 memcpy(value, p1, p2 - p1);
430 }
431 offset = strtoull(value, NULL, 10);
432 }
433
434 memset(buf, 0, sizeof(buf));
435 printf("pts=%llu, offset=%ld\n", pts, offset);
436 }
437
438 return 0;
439}