blob: a31c5dcb2569f33da96f5569eff56e9165a01b27 [file] [log] [blame]
Pengfei Liuc181a982020-01-07 19:27:13 +08001#include <stdio.h>
2#include <sys/types.h>
3#include <sys/stat.h>
4#include <fcntl.h>
5#include <string.h>
6#include <errno.h>
7#include "dvr_common.h"
8#include "segment.h"
9
10#define MAX_SEGMENT_FD_COUNT (128)
11#define MAX_SEGMENT_PATH_SIZE (DVR_MAX_LOCATION_SIZE + 32)
12typedef struct {
13 //char location[DVR_MAX_LOCATION_SIZE];
14 //uint64_t segment_id;
15 FILE *ts_fp; /**< segment ts file fd*/
16 FILE *index_fp; /**< time index file fd*/
17} Segment_Context_t;
18
19typedef enum {
20 SEGMENT_FILE_TYPE_TS,
21 SEGMENT_FILE_TYPE_INDEX,
22} Segment_FileType_t;
23
24static void segment_get_fname(char fname[MAX_SEGMENT_PATH_SIZE],
25 char location[DVR_MAX_LOCATION_SIZE],
26 uint64_t segment_id,
27 Segment_FileType_t type)
28{
29 int offset;
30
31 memset(fname, 0, MAX_SEGMENT_PATH_SIZE);
32 strncpy(fname, location, strlen(location));
33 offset = strlen(location);
34 strncpy(fname + offset, "-", 1);
35 offset += 1;
36 sprintf(fname + offset, "%04llu", segment_id);
37 offset += 4;
38 if (type == SEGMENT_FILE_TYPE_TS)
39 strncpy(fname + offset, ".ts", 3);
40 else if (type == SEGMENT_FILE_TYPE_INDEX)
41 strncpy(fname + offset, ".idx", 4);
42}
43
44int segment_open(Segment_OpenParams_t *params, Segment_Handle_t *p_handle)
45{
46 Segment_Context_t *p_ctx;
47 char ts_fname[MAX_SEGMENT_PATH_SIZE];
48 char index_fname[MAX_SEGMENT_PATH_SIZE];
49
50 DVR_ASSERT(params);
51 DVR_ASSERT(p_handle);
52
53 DVR_DEBUG(1, "%s, location:%s, id:%d", __func__, params->location, params->segment_id);
54
55 p_ctx = malloc(sizeof(Segment_Context_t));
56 DVR_ASSERT(p_ctx);
57
58 memset(ts_fname, 0, sizeof(ts_fname));
59 segment_get_fname(ts_fname, params->location, params->segment_id, SEGMENT_FILE_TYPE_TS);
60
61 memset(index_fname, 0, sizeof(index_fname));
62 segment_get_fname(index_fname, params->location, params->segment_id, SEGMENT_FILE_TYPE_INDEX);
63
64 if (params->mode == SEGMENT_MODE_READ) {
65 p_ctx->ts_fp = fopen(ts_fname, "r");
66 p_ctx->index_fp = fopen(index_fname, "r");
67 } else if (params->mode == SEGMENT_MODE_WRITE) {
68 p_ctx->ts_fp = fopen(ts_fname, "w+");
69 p_ctx->index_fp = fopen(index_fname, "w+");
70 } else {
71 DVR_DEBUG(1, "%s, unknow mode use default", __func__);
72 p_ctx->ts_fp = fopen(ts_fname, "r");
73 p_ctx->index_fp = fopen(index_fname, "r");
74 }
75
76 if (!p_ctx->ts_fp || !p_ctx->index_fp) {
77 DVR_DEBUG(1, "%s open file failed [%p, %p], reason:%s", __func__,
78 p_ctx->ts_fp, p_ctx->index_fp, strerror(errno));
79 free(p_ctx);
80 p_handle = NULL;
81 return DVR_FAILURE;
82 }
83 p_handle = p_ctx;
84 return DVR_SUCCESS;
85}
86
87int segment_close(Segment_Handle_t handle)
88{
89 Segment_Context_t *p_ctx;
90
91 p_ctx = (Segment_Context_t *)handle;
92 DVR_ASSERT(p_ctx);
93
94 if (p_ctx->ts_fp) {
95 fclose(p_ctx->ts_fp);
96 }
97
98 if (p_ctx->index_fp) {
99 fclose(p_ctx->index_fp);
100 }
101
102 free(p_ctx);
103 return 0;
104}
105
106ssize_t segment_read(Segment_Handle_t handle, void *buf, size_t count)
107{
108 Segment_Context_t *p_ctx;
109
110 p_ctx = (Segment_Context_t *)handle;
111 DVR_ASSERT(p_ctx);
112 DVR_ASSERT(buf);
113 DVR_ASSERT(p_ctx->ts_fp);
114
115 return fread(p_ctx->ts_fp, 1, count, buf);
116}
117
118ssize_t segment_write(Segment_Handle_t handle, void *buf, size_t count)
119{
120 Segment_Context_t *p_ctx;
121
122 p_ctx = (Segment_Context_t *)handle;
123 DVR_ASSERT(p_ctx);
124 DVR_ASSERT(buf);
125 DVR_ASSERT(p_ctx->ts_fp);
126
127 return fwrite(p_ctx->ts_fp, 1, count, buf);
128}
129
130int segment_update_pts(Segment_Handle_t handle, uint64_t pts, off_t offset)
131{
132 Segment_Context_t *p_ctx;
133 char buf[256];
134
135 p_ctx = (Segment_Context_t *)handle;
136 DVR_ASSERT(p_ctx);
137 DVR_ASSERT(p_ctx->index_fp);
138
139 memset(buf, 0, sizeof(buf));
140 sprintf(buf, "{pts=%llu, offset=%llu}\n", pts, offset);
141
142 fputs(buf, p_ctx->index_fp);
143 return DVR_SUCCESS;
144}
145
146off_t segment_seek(Segment_Handle_t handle, uint64_t time)
147{
148 Segment_Context_t *p_ctx;
149 char buf[256];
150 char value[256];
151 uint64_t pts;
152 off_t offset;
153 char *p1, *p2;
154
155 p_ctx = (Segment_Context_t *)handle;
156 DVR_ASSERT(p_ctx);
157 DVR_ASSERT(p_ctx->index_fp);
158 DVR_ASSERT(p_ctx->ts_fp);
159
160 memset(buf, 0, sizeof(buf));
161 DVR_ASSERT(fseek(p_ctx->index_fp, 0, SEEK_SET) != -1);
162
163 while (fgets(buf, sizeof(buf), p_ctx->index_fp) != NULL) {
164 memset(value, 0, sizeof(value));
165 if ((p1 = strstr(buf, "pts="))) {
166 p1 += 4;
167 if ((p2 = strstr(buf, ","))) {
168 memcpy(value, p1, p2 - p1);
169 }
170 pts = strtoull(value, NULL, 10);
171 }
172
173 memset(value, 0, sizeof(value));
174 if ((p1 = strstr(buf, "offset="))) {
175 p1 += 7;
176 if ((p2 = strstr(buf, "}"))) {
177 memcpy(value, p1, p2 - p1);
178 }
179 offset = strtoull(value, NULL, 10);
180 }
181
182 memset(buf, 0, sizeof(buf));
183 DVR_DEBUG(1, "pts=%llu, offset=%ld\n", pts, offset);
184 if (time < pts) {
185 DVR_ASSERT(fseeko(p_ctx->ts_fp, offset, SEEK_SET) != -1);
186 return offset;
187 }
188 }
189
190 return DVR_FAILURE;
191}
192
193off_t segment_tell(Segment_Handle_t handle)
194{
195 Segment_Context_t *p_ctx;
196
197 p_ctx = (Segment_Context_t *)handle;
198 DVR_ASSERT(p_ctx);
199 DVR_ASSERT(p_ctx->ts_fp);
200
201 return ftello(p_ctx->ts_fp);
202}