blob: 16ea23e2f62c9e2ab9d1428d26904d1ab1ceea96
1 | #define LOG_TAG "CTvRecord" |
2 | |
3 | #include <string.h> |
4 | #include <fcntl.h> |
5 | #include <sys/ioctl.h> |
6 | #include <am_debug.h> |
7 | #include <am_dmx.h> |
8 | #include <am_av.h> |
9 | |
10 | #include <am_misc.h> |
11 | |
12 | #include <am_fend.h> |
13 | #include <am_dvr.h> |
14 | #include <errno.h> |
15 | #include "CTvProgram.h" |
16 | #include "../tvconfig/tvconfig.h" |
17 | #include "CTvRecord.h" |
18 | |
19 | #define FEND_DEV_NO 0 |
20 | #define DVR_DEV_NO 0 |
21 | #define DVR_BUF_SIZE 1024*1024 |
22 | #define DVR_DEV_COUNT (2) |
23 | |
24 | typedef struct { |
25 | int id; |
26 | char file_name[256]; |
27 | pthread_t thread; |
28 | int running; |
29 | int fd; |
30 | } DVRData; |
31 | |
32 | static DVRData data_threads[DVR_DEV_COUNT]; |
33 | int pvr_init = 0; |
34 | CTvRecord::CTvRecord() |
35 | { |
36 | AM_DVR_OpenPara_t dpara; |
37 | memset(&dpara, 0, sizeof(dpara)); |
38 | AM_DVR_Open(DVR_DEV_NO, &dpara); |
39 | data_threads[DVR_DEV_NO].id = 0; |
40 | data_threads[DVR_DEV_NO].fd = -1; |
41 | data_threads[DVR_DEV_NO].running = 0; |
42 | |
43 | AM_DVR_SetSource(DVR_DEV_NO, AM_DVR_SRC_ASYNC_FIFO0); |
44 | AM_DVR_SetBufferSize(DVR_DEV_NO, DVR_BUF_SIZE); |
45 | |
46 | memset(filename, 0, sizeof(filename)); |
47 | progid = 0xFFFF; |
48 | vpid = 0x1fff; |
49 | apid = 0x1fff; |
50 | } |
51 | CTvRecord::~CTvRecord() |
52 | { |
53 | AM_DVR_Close(DVR_DEV_NO); |
54 | |
55 | } |
56 | void CTvRecord::dvr_init(void) |
57 | { |
58 | AM_DVR_OpenPara_t para; |
59 | char buf[32]; |
60 | |
61 | if (pvr_init) |
62 | return; |
63 | |
64 | memset(¶, 0, sizeof(para)); |
65 | LOGD("%s,%d", "TV", __LINE__); |
66 | |
67 | AM_DVR_Open(DVR_DEV_NO, ¶); |
68 | AM_DVR_SetSource(DVR_DEV_NO, AM_DVR_SRC_ASYNC_FIFO0); |
69 | AM_DVR_SetBufferSize(DVR_DEV_NO, DVR_BUF_SIZE); |
70 | |
71 | snprintf(buf, sizeof(buf), "%d", (512 * 1024)); |
72 | AM_FileEcho("/sys/class/dmx/asyncfifo_len", buf); |
73 | |
74 | pvr_init = 1; |
75 | } |
76 | |
77 | char *CTvRecord::GetRecordFileName() |
78 | { |
79 | return filename; |
80 | } |
81 | void CTvRecord::SetRecordFileName(char *name) |
82 | { |
83 | strcpy(filename, name); |
84 | } |
85 | void CTvRecord::SetCurRecProgramId(int id) |
86 | { |
87 | progid = id; |
88 | } |
89 | |
90 | int CTvRecord::dvr_data_write(int fd, uint8_t *buf, int size) |
91 | { |
92 | int ret; |
93 | int left = size; |
94 | uint8_t *p = buf; |
95 | LOGD("%s,%d", "TV", __LINE__); |
96 | |
97 | while (left > 0) { |
98 | ret = write(fd, p, left); |
99 | if (ret == -1) { |
100 | if (errno != EINTR) { |
101 | LOGD("Write DVR data failed: %s", strerror(errno)); |
102 | break; |
103 | } |
104 | ret = 0; |
105 | } |
106 | |
107 | left -= ret; |
108 | p += ret; |
109 | } |
110 | |
111 | return (size - left); |
112 | } |
113 | void *CTvRecord::dvr_data_thread(void *arg) |
114 | { |
115 | DVRData *dd = (DVRData *)arg; |
116 | int cnt; |
117 | uint8_t buf[256 * 1024]; |
118 | |
119 | LOGD("Data thread for DVR%d start ,record file will save to '%s'", dd->id, dd->file_name); |
120 | LOGD("%s,%d", "TV", __LINE__); |
121 | |
122 | while (dd->running) { |
123 | cnt = AM_DVR_Read(dd->id, buf, sizeof(buf), 1000); |
124 | if (cnt <= 0) { |
125 | LOGD("No data available from DVR%d", dd->id); |
126 | usleep(200 * 1000); |
127 | continue; |
128 | } |
129 | //AM_DEBUG(1, "read from DVR%d return %d bytes", dd->id, cnt); |
130 | if (dd->fd != -1) { |
131 | dvr_data_write(dd->fd, buf, cnt); |
132 | } |
133 | } |
134 | |
135 | if (dd->fd != -1) { |
136 | close(dd->fd); |
137 | dd->fd = -1; |
138 | } |
139 | LOGD("Data thread for DVR%d now exit", dd->id); |
140 | |
141 | return NULL; |
142 | } |
143 | |
144 | void CTvRecord::start_data_thread(int dev_no) |
145 | { |
146 | DVRData *dd = &data_threads[dev_no]; |
147 | |
148 | if (dd->running) |
149 | return; |
150 | LOGD("%s,%d,dev=%d", "TV", __LINE__, dev_no); |
151 | dd->fd = open(dd->file_name, O_TRUNC | O_WRONLY | O_CREAT, 0666); |
152 | if (dd->fd == -1) { |
153 | LOGD("Cannot open record file '%s' for DVR%d, %s", dd->file_name, dd->id, strerror(errno)); |
154 | return; |
155 | } |
156 | dd->running = 1; |
157 | pthread_create(&dd->thread, NULL, dvr_data_thread, dd); |
158 | } |
159 | void CTvRecord::get_cur_program_pid(int progId) |
160 | { |
161 | CTvProgram prog; |
162 | int aindex; |
163 | CTvProgram::Audio *pA; |
164 | CTvProgram::Video *pV; |
165 | int ret = CTvProgram::selectByID(progId, prog); |
166 | if (ret != 0) return; |
167 | |
168 | LOGD("%s,%d", "TV", __LINE__); |
169 | pV = prog.getVideo(); |
170 | if (pV != NULL) { |
171 | setvpid(pV->getPID()); |
172 | } |
173 | |
174 | aindex = prog.getCurrAudioTrackIndex(); |
175 | if (-1 == aindex) { //db is default |
176 | aindex = prog.getCurrentAudio(String8("eng")); |
177 | if (aindex >= 0) { |
178 | prog.setCurrAudioTrackIndex(progId, aindex); |
179 | } |
180 | } |
181 | |
182 | if (aindex >= 0) { |
183 | pA = prog.getAudio(aindex); |
184 | if (pA != NULL) { |
185 | setapid(pA->getPID()); |
186 | } |
187 | } |
188 | |
189 | } |
190 | int CTvRecord::start_dvr() |
191 | { |
192 | AM_DVR_StartRecPara_t spara; |
193 | int pid_cnt; |
194 | int pids[2]; |
195 | |
196 | /**½ö²âÊÔ×î¶à8¸öPID*/ |
197 | get_cur_program_pid(progid); |
198 | pids[0] = getvpid(); |
199 | pids[1] = getapid(); |
200 | |
201 | strcpy(data_threads[DVR_DEV_NO].file_name, GetRecordFileName()); |
202 | LOGD("%s,%d", "TV", __LINE__); |
203 | //sprintf(data_threads[DVR_DEV_NO].file_name,"%s","/storage/external_storage/sda4/testdvr.ts"); |
204 | spara.pid_count = 2; |
205 | memcpy(&spara.pids, pids, sizeof(pids)); |
206 | |
207 | if (AM_DVR_StartRecord(DVR_DEV_NO, &spara) == AM_SUCCESS) { |
208 | start_data_thread(DVR_DEV_NO); |
209 | } |
210 | |
211 | return 0; |
212 | } |
213 | void CTvRecord::stop_data_thread(int dev_no) |
214 | { |
215 | DVRData *dd = &data_threads[dev_no]; |
216 | LOGD("%s,%d", "TV", __LINE__); |
217 | |
218 | if (! dd->running) |
219 | return; |
220 | dd->running = 0; |
221 | pthread_join(dd->thread, NULL); |
222 | LOGD("Data thread for DVR%d has exit", dd->id); |
223 | } |
224 | |
225 | |
226 | void CTvRecord::StartRecord(int id) |
227 | { |
228 | AM_DVR_OpenPara_t dpara; |
229 | fe_status_t status; |
230 | char buf[32]; |
231 | |
232 | AM_FEND_GetStatus(FEND_DEV_NO, &status); |
233 | |
234 | if (status & FE_HAS_LOCK) { |
235 | LOGD("locked\n"); |
236 | } else { |
237 | LOGD("unlocked\n"); |
238 | return ; |
239 | } |
240 | SetCurRecProgramId(id); |
241 | start_dvr(); |
242 | |
243 | return; |
244 | } |
245 | void CTvRecord::StopRecord() |
246 | { |
247 | int i = 0; |
248 | LOGD("stop record for %d", DVR_DEV_NO); |
249 | AM_DVR_StopRecord(DVR_DEV_NO); |
250 | |
251 | //for (i=0; i< DVR_DEV_COUNT; i++) |
252 | { |
253 | if (data_threads[DVR_DEV_NO].running) |
254 | stop_data_thread(DVR_DEV_NO); |
255 | //LOGD("Closing DMX%d...", i); |
256 | } |
257 | |
258 | |
259 | } |
260 | void CTvRecord::SetRecCurTsOrCurProgram(int sel) |
261 | { |
262 | int i = 0; |
263 | char buf[50]; |
264 | memset(buf, 0, sizeof(buf)); |
265 | for (; i < 3; i++) { |
266 | snprintf(buf, sizeof(buf), "/sys/class/stb/dvr%d_mode", i); |
267 | if (sel) |
268 | AM_FileEcho(buf, "ts"); |
269 | else |
270 | AM_FileEcho(buf, "pid"); |
271 | } |
272 | } |
273 | |
274 |