• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  */
15 
16 /**************************************************
17 * example based on amcodec
18 **************************************************/
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/mman.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <signal.h>
28 #include <errno.h>
29 #include <stdbool.h>
30 #include <ctype.h>
31 #include <codec.h>
32 #include <amvideo.h>
33 #include <IONmem.h>
34 
35 #define READ_SIZE (64 * 1024)
36 #define EXTERNAL_PTS    (1)
37 #define SYNC_OUTSIDE    (2)
38 #define UNIT_FREQ       96000
39 #define PTS_FREQ        90000
40 #define AV_SYNC_THRESH    PTS_FREQ*30
41 #define MESON_BUFFER_SIZE 4
42 
43 static codec_para_t v_codec_para;
44 static codec_para_t *vpcodec;
45 #ifdef AUDIO_ES
46 static codec_para_t a_codec_para;
47 static codec_para_t *apcodec;
48 #endif
49 static codec_para_t *pcodec;
50 static char *filename;
51 FILE* fp = NULL;
52 FILE* yuv = NULL;
53 static int axis[8] = {0};
54 struct amvideo_dev *amvideo;
55 
56 struct out_buffer_t {
57     int index;
58     int size;
59     bool own_by_v4l;
60     void *ptr;
61     IONMEM_AllocParams buffer;
62 } vbuffer[MESON_BUFFER_SIZE];
63 
amsysfs_set_sysfs_str(const char * path,const char * val)64 static int amsysfs_set_sysfs_str(const char *path, const char *val)
65 {
66     int fd;
67     int bytes;
68     fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644);
69     if (fd >= 0) {
70         bytes = write(fd, val, strlen(val));
71         close(fd);
72         return 0;
73     } else {
74         printf("unable to open file %s,err: %s\n", path, strerror(errno));
75     }
76     return -1;
77 }
78 
osd_blank(char * path,int cmd)79 int osd_blank(char *path, int cmd)
80 {
81     int fd;
82     char  bcmd[16];
83     fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644);
84 
85     if (fd >= 0) {
86         sprintf(bcmd, "%d", cmd);
87         write(fd, bcmd, strlen(bcmd));
88         close(fd);
89         return 0;
90     }
91 
92     return -1;
93 }
94 
set_tsync_enable(int enable)95 int set_tsync_enable(int enable)
96 {
97     int fd;
98     char *path = "/sys/class/tsync/enable";
99     char  bcmd[16];
100     fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644);
101     if (fd >= 0) {
102         sprintf(bcmd, "%d", enable);
103         write(fd, bcmd, strlen(bcmd));
104         close(fd);
105         return 0;
106     }
107 
108     return -1;
109 }
110 
parse_para(const char * para,int para_num,int * result)111 int parse_para(const char *para, int para_num, int *result)
112 {
113     char *endp;
114     const char *startp = para;
115     int *out = result;
116     int len = 0, count = 0;
117 
118     if (!startp) {
119         return 0;
120     }
121 
122     len = strlen(startp);
123 
124     do {
125         //filter space out
126         while (startp && (isspace(*startp) || !isgraph(*startp)) && len) {
127             startp++;
128             len--;
129         }
130 
131         if (len == 0) {
132             break;
133         }
134 
135         *out++ = strtol(startp, &endp, 0);
136 
137         len -= endp - startp;
138         startp = endp;
139         count++;
140 
141     } while ((endp) && (count < para_num) && (len > 0));
142 
143     return count;
144 }
145 
set_display_axis(int recovery)146 int set_display_axis(int recovery)
147 {
148     int fd;
149     char *path = "/sys/class/display/axis";
150     char str[128];
151     int count;
152     fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644);
153     if (fd >= 0) {
154         if (!recovery) {
155             read(fd, str, 128);
156             printf("read axis %s, length %d\n", str, strlen(str));
157             count = parse_para(str, 8, axis);
158         }
159         if (recovery) {
160             sprintf(str, "%d %d %d %d %d %d %d %d",
161                     axis[0], axis[1], axis[2], axis[3], axis[4], axis[5], axis[6], axis[7]);
162         } else {
163             sprintf(str, "2048 %d %d %d %d %d %d %d",
164                     axis[1], axis[2], axis[3], axis[4], axis[5], axis[6], axis[7]);
165         }
166         write(fd, str, strlen(str));
167         close(fd);
168         return 0;
169     }
170 
171     return -1;
172 }
FreeBuffers()173 static void FreeBuffers()
174 {
175     int i;
176     for (i = 0; i < MESON_BUFFER_SIZE; i++) {
177         if (vbuffer[i].ptr) {
178             CMEM_free(&vbuffer[i].buffer);
179         }
180     }
181 }
AllocBuffers(int width,int height)182 static int AllocBuffers(int width, int height)
183 {
184     int i, size, ret;
185     CMEM_init();
186     size = width * height * 3 / 2;
187     for (i = 0; i < MESON_BUFFER_SIZE; i++) {
188         ret = CMEM_alloc(size, &vbuffer[i].buffer);
189         if (ret < 0) {
190             printf("CMEM_alloc failed\n");
191             FreeBuffers();
192             goto fail;
193         }
194         vbuffer[i].index = i;
195         vbuffer[i].size = size;
196         vbuffer[i].ptr = vbuffer[i].buffer.vaddr;
197     }
198 fail:
199     return ret;
200 }
ionvideo_init(int width,int height)201 static int ionvideo_init(int width, int height)
202 {
203     int i, ret;
204 
205 
206     amsysfs_set_sysfs_str("/sys/class/vfm/map", "rm default");
207     amsysfs_set_sysfs_str("/sys/class/vfm/map",
208                "add default decoder ionvideo");
209 
210     ret = AllocBuffers(width, height);
211     if (ret < 0) {
212         printf("AllocBuffers failed\n");
213         ret = -ENODEV;
214         goto fail;
215     }
216 
217     amvideo = new_amvideo(FLAGS_V4L_MODE);
218     if (!amvideo) {
219         printf("amvideo create failed\n");
220         ret = -ENODEV;
221         goto fail;
222     }
223     amvideo->display_mode = 0;
224     amvideo->use_frame_mode = 0;
225 
226     ret = amvideo_init(amvideo, 0, width, height,
227             V4L2_PIX_FMT_NV12, MESON_BUFFER_SIZE);
228     if (ret < 0) {
229         printf("amvideo_init failed\n");
230         amvideo_release(amvideo);
231         goto fail;
232     }
233     ret = amvideo_start(amvideo);
234     if (ret < 0) {
235         amvideo_release(amvideo);
236         goto fail;
237     }
238     for (i = 0; i < MESON_BUFFER_SIZE; i++) {
239         vframebuf_t vf;
240         vf.fd = vbuffer[i].buffer.mIonHnd;
241         vf.length = vbuffer[i].buffer.size;
242         vf.index = vbuffer[i].index;
243         ret = amlv4l_queuebuf(amvideo, &vf);
244     }
245 fail:
246     return ret;
247 }
248 
ionvideo_close()249 static void ionvideo_close()
250 {
251     amvideo_stop(amvideo);
252     amvideo_release(amvideo);
253 }
254 
signal_handler(int signum)255 static void signal_handler(int signum)
256 {
257     printf("Get signum=%x\n", signum);
258 #ifdef AUDIO_ES
259     codec_close(apcodec);
260 #endif
261     codec_close(vpcodec);
262     fclose(fp);
263     set_display_axis(1);
264     signal(signum, SIG_DFL);
265     raise(signum);
266     ionvideo_close();
267     FreeBuffers();
268 }
269 
main(int argc,char * argv[])270 int main(int argc, char *argv[])
271 {
272     int ret = CODEC_ERROR_NONE;
273     char buffer[READ_SIZE];
274 
275     uint32_t Readlen;
276     uint32_t isize;
277     struct buf_status vbuf;
278 
279     if (argc < 6) {
280         printf("Corret command: ionplayer <filename> <width> <height> <fps> <format(1:mpeg4 2:h264)> [subformat for mpeg4]\n");
281         return -1;
282     }
283 #if 0
284     if (osd_blank("/sys/class/graphics/fb0/blank", 1) < 0)
285         osd_blank("/sys/kernel/debug/dri/0/vpu/blank", 1);
286     if (osd_blank("/sys/class/graphics/fb1/blank", 0) < 0)
287         osd_blank("/sys/kernel/debug/dri/64/vpu/blank", 1);
288 #endif
289     set_display_axis(0);
290 #ifdef AUDIO_ES
291     apcodec = &a_codec_para;
292     memset(apcodec, 0, sizeof(codec_para_t));
293 #endif
294 
295     vpcodec = &v_codec_para;
296     memset(vpcodec, 0, sizeof(codec_para_t));
297 
298     vpcodec->has_video = 1;
299     vpcodec->video_type = atoi(argv[5]);
300     if (vpcodec->video_type == VFORMAT_H264) {
301         vpcodec->am_sysinfo.format = VIDEO_DEC_FORMAT_H264;
302         vpcodec->am_sysinfo.param = (void *)(EXTERNAL_PTS | SYNC_OUTSIDE);
303     } else if (vpcodec->video_type == VFORMAT_MPEG4) {
304         if (argc < 7) {
305             printf("No subformat for mpeg4, take the default VIDEO_DEC_FORMAT_MPEG4_5\n");
306             vpcodec->am_sysinfo.format = VIDEO_DEC_FORMAT_MPEG4_5;
307         } else {
308             vpcodec->am_sysinfo.format = atoi(argv[6]);
309         }
310     }
311 
312     vpcodec->stream_type = STREAM_TYPE_ES_VIDEO;
313     vpcodec->am_sysinfo.rate = 96000 / atoi(argv[4]);
314     vpcodec->am_sysinfo.height = atoi(argv[3]);
315     vpcodec->am_sysinfo.width = atoi(argv[2]);
316     vpcodec->has_audio = 0;
317     vpcodec->noblock = 0;
318 
319 #ifdef AUDIO_ES
320     apcodec->audio_type = AFORMAT_MPEG;
321     apcodec->stream_type = STREAM_TYPE_ES_AUDIO;
322     apcodec->audio_pid = 0x1023;
323     apcodec->has_audio = 1;
324     apcodec->audio_channels = 2;
325     apcodec->audio_samplerate = 48000;
326     apcodec->noblock = 0;
327     apcodec->audio_info.channels = 2;
328     apcodec->audio_info.sample_rate = 48000;
329 #endif
330 
331     printf("\n*********CODEC PLAYER DEMO************\n\n");
332     filename = argv[1];
333     printf("file %s to be played\n", filename);
334 
335     if ((fp = fopen(filename, "rb")) == NULL) {
336         printf("open file error!\n");
337         return -1;
338     }
339 
340     if ((yuv = fopen("./yuv.yuv", "wb")) == NULL) {
341         printf("./yuv.yuv dump open file error!\n");
342         return -1;
343     }
344 
345     ionvideo_init(vpcodec->am_sysinfo.width, vpcodec->am_sysinfo.height);
346 #ifdef AUDIO_ES
347     ret = codec_init(apcodec);
348     if (ret != CODEC_ERROR_NONE) {
349         printf("codec init failed, ret=-0x%x", -ret);
350         return -1;
351     }
352 #endif
353 
354     ret = codec_init(vpcodec);
355     if (ret != CODEC_ERROR_NONE) {
356         printf("codec init failed, ret=-0x%x", -ret);
357         return -1;
358     }
359     printf("video codec ok!\n");
360 
361     //codec_set_cntl_avthresh(vpcodec, AV_SYNC_THRESH);
362     //codec_set_cntl_syncthresh(vpcodec, 0);
363 
364     set_tsync_enable(0);
365 
366     pcodec = vpcodec;
367     while (!feof(fp)) {
368         Readlen = fread(buffer, 1, READ_SIZE, fp);
369         printf("Readlen %d\n", Readlen);
370         if (Readlen <= 0) {
371             printf("read file error!\n");
372             rewind(fp);
373         }
374 
375         isize = 0;
376         do {
377             vframebuf_t vf;
378             ret = amlv4l_dequeuebuf(amvideo, &vf);
379             if (ret >= 0) {
380                 printf("vf idx%d pts 0x%llx\n", vf.index, vf.pts);
381                 fwrite(vbuffer[vf.index].ptr, vbuffer[vf.index].size, 1, yuv);
382 				fflush(yuv);
383                 ret = amlv4l_queuebuf(amvideo, &vf);
384                 if (ret < 0) {
385                     printf("amlv4l_queuebuf %d\n", ret);
386                 }
387             } else {
388                 printf("amlv4l_dequeuebuf %d\n", ret);
389             }
390             ret = codec_write(pcodec, buffer + isize, Readlen);
391             if (ret < 0) {
392                 if (errno != EAGAIN) {
393                     printf("write data failed, errno %d\n", errno);
394                     goto error;
395                 } else {
396                     continue;
397                 }
398             } else {
399                 isize += ret;
400             }
401 
402             printf("ret %d, isize %d\n", ret, isize);
403         } while (isize < Readlen);
404 
405         signal(SIGCHLD, SIG_IGN);
406         signal(SIGTSTP, SIG_IGN);
407         signal(SIGTTOU, SIG_IGN);
408         signal(SIGTTIN, SIG_IGN);
409         signal(SIGHUP, signal_handler);
410         signal(SIGTERM, signal_handler);
411         signal(SIGSEGV, signal_handler);
412         signal(SIGINT, signal_handler);
413         signal(SIGQUIT, signal_handler);
414     }
415 
416     do {
417         vframebuf_t vf;
418         ret = codec_get_vbuf_state(pcodec, &vbuf);
419         if (ret != 0) {
420             printf("codec_get_vbuf_state error: %x\n", -ret);
421             goto error;
422         }
423 
424         ret = amlv4l_dequeuebuf(amvideo, &vf);
425         if (ret >= 0) {
426             printf("vf idx%d pts 0x%llx\n", vf.index, vf.pts);
427             fwrite(vbuffer[vf.index].ptr, vbuffer[vf.index].size, 1, yuv);
428 			fflush(yuv);
429             ret = amlv4l_queuebuf(amvideo, &vf);
430             if (ret < 0) {
431                 //printf("amlv4l_queuebuf %d\n", ret);
432             }
433         } else {
434             //printf("amlv4l_dequeuebuf %d\n", ret);
435         }
436     } while (vbuf.data_len > 0x100);
437 
438 error:
439 #ifdef AUDIO_ES
440     codec_close(apcodec);
441 #endif
442     codec_close(vpcodec);
443     fclose(fp);
444     fclose(yuv);
445     set_display_axis(1);
446     ionvideo_close();
447     FreeBuffers();
448     return 0;
449 }
450 
451