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