blob: 3b7f31ba8272bebf661707e45f25a1f0bbc929f1 [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 Liuc181a982020-01-07 19:27:13 +080015typedef struct {
16 //char location[DVR_MAX_LOCATION_SIZE];
17 //uint64_t segment_id;
Pengfei Liub038b6a2020-01-14 15:57:01 +080018 FILE *ts_fp; /**< segment ts file fd*/
19 FILE *index_fp; /**< time index file fd*/
20 uint64_t first_pts; /**< first pts value, use for write mode*/
21 uint64_t last_pts; /**< last pts value, use for write mode*/
Pengfei Liuc181a982020-01-07 19:27:13 +080022} Segment_Context_t;
23
24typedef enum {
25 SEGMENT_FILE_TYPE_TS,
26 SEGMENT_FILE_TYPE_INDEX,
27} Segment_FileType_t;
28
29static void segment_get_fname(char fname[MAX_SEGMENT_PATH_SIZE],
30 char location[DVR_MAX_LOCATION_SIZE],
31 uint64_t segment_id,
32 Segment_FileType_t type)
33{
34 int offset;
35
36 memset(fname, 0, MAX_SEGMENT_PATH_SIZE);
37 strncpy(fname, location, strlen(location));
38 offset = strlen(location);
39 strncpy(fname + offset, "-", 1);
40 offset += 1;
41 sprintf(fname + offset, "%04llu", segment_id);
42 offset += 4;
43 if (type == SEGMENT_FILE_TYPE_TS)
44 strncpy(fname + offset, ".ts", 3);
45 else if (type == SEGMENT_FILE_TYPE_INDEX)
46 strncpy(fname + offset, ".idx", 4);
47}
48
49int segment_open(Segment_OpenParams_t *params, Segment_Handle_t *p_handle)
50{
51 Segment_Context_t *p_ctx;
52 char ts_fname[MAX_SEGMENT_PATH_SIZE];
53 char index_fname[MAX_SEGMENT_PATH_SIZE];
54
55 DVR_ASSERT(params);
56 DVR_ASSERT(p_handle);
57
Pengfei Liub038b6a2020-01-14 15:57:01 +080058 DVR_DEBUG(1, "%s, location:%s, id:%llu", __func__, params->location, params->segment_id);
Pengfei Liuc181a982020-01-07 19:27:13 +080059
Pengfei Liub038b6a2020-01-14 15:57:01 +080060 p_ctx = (void*)malloc(sizeof(Segment_Context_t));
Pengfei Liuc181a982020-01-07 19:27:13 +080061 DVR_ASSERT(p_ctx);
62
63 memset(ts_fname, 0, sizeof(ts_fname));
64 segment_get_fname(ts_fname, params->location, params->segment_id, SEGMENT_FILE_TYPE_TS);
65
66 memset(index_fname, 0, sizeof(index_fname));
67 segment_get_fname(index_fname, params->location, params->segment_id, SEGMENT_FILE_TYPE_INDEX);
68
69 if (params->mode == SEGMENT_MODE_READ) {
70 p_ctx->ts_fp = fopen(ts_fname, "r");
71 p_ctx->index_fp = fopen(index_fname, "r");
72 } else if (params->mode == SEGMENT_MODE_WRITE) {
73 p_ctx->ts_fp = fopen(ts_fname, "w+");
74 p_ctx->index_fp = fopen(index_fname, "w+");
Pengfei Liub038b6a2020-01-14 15:57:01 +080075 p_ctx->first_pts = ULLONG_MAX;
76 p_ctx->last_pts = ULLONG_MAX;
Pengfei Liuc181a982020-01-07 19:27:13 +080077 } else {
78 DVR_DEBUG(1, "%s, unknow mode use default", __func__);
79 p_ctx->ts_fp = fopen(ts_fname, "r");
80 p_ctx->index_fp = fopen(index_fname, "r");
81 }
82
83 if (!p_ctx->ts_fp || !p_ctx->index_fp) {
84 DVR_DEBUG(1, "%s open file failed [%p, %p], reason:%s", __func__,
85 p_ctx->ts_fp, p_ctx->index_fp, strerror(errno));
86 free(p_ctx);
Pengfei Liub038b6a2020-01-14 15:57:01 +080087 *p_handle = NULL;
Pengfei Liuc181a982020-01-07 19:27:13 +080088 return DVR_FAILURE;
89 }
Pengfei Liub038b6a2020-01-14 15:57:01 +080090 DVR_DEBUG(1, "%s, open file sucess", __func__);
91 *p_handle = (Segment_Handle_t)p_ctx;
Pengfei Liuc181a982020-01-07 19:27:13 +080092 return DVR_SUCCESS;
93}
94
95int segment_close(Segment_Handle_t handle)
96{
97 Segment_Context_t *p_ctx;
98
Pengfei Liub038b6a2020-01-14 15:57:01 +080099 p_ctx = (void *)handle;
Pengfei Liuc181a982020-01-07 19:27:13 +0800100 DVR_ASSERT(p_ctx);
101
102 if (p_ctx->ts_fp) {
103 fclose(p_ctx->ts_fp);
104 }
105
106 if (p_ctx->index_fp) {
107 fclose(p_ctx->index_fp);
108 }
109
110 free(p_ctx);
111 return 0;
112}
113
114ssize_t segment_read(Segment_Handle_t handle, void *buf, size_t count)
115{
116 Segment_Context_t *p_ctx;
117
118 p_ctx = (Segment_Context_t *)handle;
119 DVR_ASSERT(p_ctx);
120 DVR_ASSERT(buf);
121 DVR_ASSERT(p_ctx->ts_fp);
122
Pengfei Liub038b6a2020-01-14 15:57:01 +0800123 return fread(buf, 1, count, p_ctx->ts_fp);
Pengfei Liuc181a982020-01-07 19:27:13 +0800124}
125
126ssize_t segment_write(Segment_Handle_t handle, void *buf, size_t count)
127{
128 Segment_Context_t *p_ctx;
129
130 p_ctx = (Segment_Context_t *)handle;
131 DVR_ASSERT(p_ctx);
132 DVR_ASSERT(buf);
133 DVR_ASSERT(p_ctx->ts_fp);
134
Pengfei Liub038b6a2020-01-14 15:57:01 +0800135 //return fwrite(p_ctx->ts_fp, 1, count, buf);
136 return fwrite(buf, 1, count, p_ctx->ts_fp);
Pengfei Liuc181a982020-01-07 19:27:13 +0800137}
138
139int segment_update_pts(Segment_Handle_t handle, uint64_t pts, off_t offset)
140{
141 Segment_Context_t *p_ctx;
142 char buf[256];
143
144 p_ctx = (Segment_Context_t *)handle;
145 DVR_ASSERT(p_ctx);
146 DVR_ASSERT(p_ctx->index_fp);
147
Pengfei Liub038b6a2020-01-14 15:57:01 +0800148 if (p_ctx->first_pts == ULLONG_MAX) {
149 p_ctx->first_pts = pts;
150 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800151 memset(buf, 0, sizeof(buf));
Pengfei Liub038b6a2020-01-14 15:57:01 +0800152 if (p_ctx->last_pts == ULLONG_MAX) {
153 /*Last pts is init value*/
154 sprintf(buf, "{time=%llu, offset=%ld}\n", pts - p_ctx->first_pts, offset);
155 } else {
156 /*Last pts has valid value*/
157 if (pts - p_ctx->last_pts > MAX_PTS_THRESHOLD) {
158 /*Current pts has a transition*/
159 sprintf(buf, "{time=%llu, offset=%ld}\n", p_ctx->last_pts - p_ctx->first_pts, offset);
160 } else {
161 /*This is a normal pts, record it*/
162 sprintf(buf, "{time=%llu, offset=%ld}\n", pts - p_ctx->first_pts, offset);
163 }
164 }
Pengfei Liuc181a982020-01-07 19:27:13 +0800165
166 fputs(buf, p_ctx->index_fp);
Pengfei Liub038b6a2020-01-14 15:57:01 +0800167 p_ctx->last_pts = pts;
168 fflush(p_ctx->index_fp);
169 fsync(fileno(p_ctx->index_fp));
170 //fdatasync(fileno(p_ctx->index_fp));
Pengfei Liuc181a982020-01-07 19:27:13 +0800171 return DVR_SUCCESS;
172}
173
174off_t segment_seek(Segment_Handle_t handle, uint64_t time)
175{
176 Segment_Context_t *p_ctx;
177 char buf[256];
178 char value[256];
179 uint64_t pts;
180 off_t offset;
181 char *p1, *p2;
182
183 p_ctx = (Segment_Context_t *)handle;
184 DVR_ASSERT(p_ctx);
185 DVR_ASSERT(p_ctx->index_fp);
186 DVR_ASSERT(p_ctx->ts_fp);
187
188 memset(buf, 0, sizeof(buf));
189 DVR_ASSERT(fseek(p_ctx->index_fp, 0, SEEK_SET) != -1);
190
191 while (fgets(buf, sizeof(buf), p_ctx->index_fp) != NULL) {
192 memset(value, 0, sizeof(value));
Pengfei Liub038b6a2020-01-14 15:57:01 +0800193 if ((p1 = strstr(buf, "time="))) {
Pengfei Liuc181a982020-01-07 19:27:13 +0800194 p1 += 4;
195 if ((p2 = strstr(buf, ","))) {
196 memcpy(value, p1, p2 - p1);
197 }
198 pts = strtoull(value, NULL, 10);
199 }
200
201 memset(value, 0, sizeof(value));
202 if ((p1 = strstr(buf, "offset="))) {
203 p1 += 7;
204 if ((p2 = strstr(buf, "}"))) {
205 memcpy(value, p1, p2 - p1);
206 }
207 offset = strtoull(value, NULL, 10);
208 }
209
210 memset(buf, 0, sizeof(buf));
Pengfei Liub038b6a2020-01-14 15:57:01 +0800211 DVR_DEBUG(1, "time=%llu, offset=%ld\n", pts, offset);
Pengfei Liuc181a982020-01-07 19:27:13 +0800212 if (time < pts) {
213 DVR_ASSERT(fseeko(p_ctx->ts_fp, offset, SEEK_SET) != -1);
214 return offset;
215 }
216 }
217
218 return DVR_FAILURE;
219}
220
221off_t segment_tell(Segment_Handle_t handle)
222{
223 Segment_Context_t *p_ctx;
224
225 p_ctx = (Segment_Context_t *)handle;
226 DVR_ASSERT(p_ctx);
227 DVR_ASSERT(p_ctx->ts_fp);
228
229 return ftello(p_ctx->ts_fp);
230}
Pengfei Liub038b6a2020-01-14 15:57:01 +0800231
232off_t segment_dump_pts(Segment_Handle_t handle)
233{
234 Segment_Context_t *p_ctx;
235 char buf[256];
236 char value[256];
237 uint64_t pts;
238 off_t offset;
239 char *p1, *p2;
240
241 p_ctx = (Segment_Context_t *)handle;
242 DVR_ASSERT(p_ctx);
243 DVR_ASSERT(p_ctx->index_fp);
244 DVR_ASSERT(p_ctx->ts_fp);
245
246 memset(buf, 0, sizeof(buf));
247 DVR_ASSERT(fseek(p_ctx->index_fp, 0, SEEK_SET) != -1);
248 printf("start gets pts\n");
249 while (fgets(buf, sizeof(buf), p_ctx->index_fp) != NULL) {
250 printf("buf[%s]\n", buf);
251 memset(value, 0, sizeof(value));
252 if ((p1 = strstr(buf, "time="))) {
253 p1 += 4;
254 if ((p2 = strstr(buf, ","))) {
255 memcpy(value, p1, p2 - p1);
256 }
257 pts = strtoull(value, NULL, 10);
258 }
259
260 memset(value, 0, sizeof(value));
261 if ((p1 = strstr(buf, "offset="))) {
262 p1 += 7;
263 if ((p2 = strstr(buf, "}"))) {
264 memcpy(value, p1, p2 - p1);
265 }
266 offset = strtoull(value, NULL, 10);
267 }
268
269 memset(buf, 0, sizeof(buf));
270 printf("pts=%llu, offset=%ld\n", pts, offset);
271 }
272
273 return 0;
274}