port of fbff to libmpeg3
[fbff.git] / ffs.c
blob47c44b166f760d78458edc86c785febc71b0f49b
1 #include <fcntl.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <sys/time.h>
7 #include "libmpeg3.h"
8 #include "ffs.h"
10 #define AUDIOBUF (1 << 14)
11 #define SEEKBYTES (1 << 12)
13 /* ffmpeg stream */
14 struct ffs {
15 mpeg3_t *file;
16 int si; /* stream index */
18 int fmt; /* video pixel format */
19 int bpp; /* video bytes per pixel */
20 long ts; /* frame timestamp (ms) */
21 float zoom; /* video zoom */
22 char vbuf[1 << 22]; /* video buffer */
25 struct ffs *ffs_alloc(char *path, int flags)
27 struct ffs *ffs;
28 int video = flags & FFS_VIDEO;
29 ffs = malloc(sizeof(*ffs));
30 memset(ffs, 0, sizeof(*ffs));
31 ffs->file = mpeg3_open(path, NULL);
32 if (!ffs->file)
33 goto failed;
34 if ((video && !mpeg3_has_video(ffs->file)) || !mpeg3_has_audio(ffs->file))
35 goto failed;
36 mpeg3_set_cpus(ffs->file, 1);
37 return ffs;
38 failed:
39 ffs_free(ffs);
40 return NULL;
43 void ffs_free(struct ffs *ffs)
45 if (ffs->file)
46 mpeg3_close(ffs->file);
47 free(ffs);
50 static long ts_ms(void)
52 struct timeval tv;
53 gettimeofday(&tv, NULL);
54 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
57 static int wait(long ts, int vdelay)
59 int nts = ts_ms();
60 if (nts > ts && ts + vdelay > nts) {
61 usleep((ts + vdelay - nts) * 1000);
62 return 0;
64 return 1;
67 void ffs_wait(struct ffs *ffs)
69 int vdelay = 1000 / mpeg3_frame_rate(ffs->file, ffs->si);
70 if (!wait(ffs->ts, MAX(vdelay, 20)))
71 ffs->ts += MAX(vdelay, 20);
72 else
73 ffs->ts = ts_ms(); /* out of sync */
76 long ffs_pos(struct ffs *ffs, int diff)
78 return mpeg3_tell_byte(ffs->file) + diff * SEEKBYTES;
81 void ffs_seek(struct ffs *ffs, long pos, int perframe)
83 mpeg3_seek_byte(ffs->file, pos);
86 /* can more video packets be read */
87 int ffs_avdiff(struct ffs *ffs, struct ffs *affs)
89 return mpeg3_get_time(affs->file) - mpeg3_get_time(ffs->file);
92 void ffs_vinfo(struct ffs *ffs, int *w, int *h)
94 *h = mpeg3_video_height(ffs->file, ffs->si);
95 *w = mpeg3_video_width(ffs->file, ffs->si);
98 void ffs_ainfo(struct ffs *ffs, int *rate, int *bps, int *ch)
100 *rate = mpeg3_sample_rate(ffs->file, ffs->si);
101 *ch = mpeg3_audio_channels(ffs->file, ffs->si) == 1 ? 1 : 2;
102 *bps = 16;
105 int ffs_vdec(struct ffs *ffs, void **buf)
107 unsigned char *rows[1 << 11];
108 int mw, mh, w, h;
109 int i;
110 int ret;
111 if (mpeg3_end_of_video(ffs->file, ffs->si))
112 return -1;
113 ffs_vinfo(ffs, &mw, &mh);
114 w = mw * ffs->zoom;
115 h = mh * ffs->zoom;
116 for (i = 0; i < h; i++)
117 rows[i] = (void *) ffs->vbuf + i * w * ffs->bpp;
118 ret = mpeg3_read_frame(ffs->file, rows, 0, 0, mw, mh, w, h, ffs->fmt, ffs->si);
119 *buf = ffs->vbuf;
120 return ret ? 0 : w * ffs->bpp;
123 int ffs_adec(struct ffs *ffs, void *buf, int blen)
125 int16_t ch1[AUDIOBUF];
126 int16_t ch2[AUDIOBUF];
127 int16_t *out = buf;
128 int ch = mpeg3_audio_channels(ffs->file, ffs->si) == 1 ? 1 : 2;
129 int i;
130 if (mpeg3_end_of_audio(ffs->file, ffs->si))
131 return -1;
132 if (mpeg3_read_audio(ffs->file, NULL, ch1, 0, AUDIOBUF, ffs->si))
133 return 0;
134 if (ch > 1)
135 if (mpeg3_reread_audio(ffs->file, NULL, ch2, 1, AUDIOBUF, ffs->si))
136 return 0;
137 for (i = 0; i < AUDIOBUF; i++) {
138 out[i * ch] = ch1[i];
139 if (ch > 1)
140 out[i * ch + 1] = ch2[i];
142 return AUDIOBUF * 4;
145 static int fbm2pixfmt(int fbm)
147 switch (fbm & 0x0fff) {
148 case 0x888:
149 return MPEG3_BGRA8888;
150 case 0x565:
151 return MPEG3_RGB565;
152 default:
153 fprintf(stderr, "ffs: unknown fb_mode()\n");
154 return MPEG3_RGB888;
158 void ffs_vconf(struct ffs *ffs, float zoom, int fbm)
160 ffs->fmt = fbm2pixfmt(fbm);
161 ffs->zoom = zoom;
162 ffs->bpp = (fbm >> 16) & 0x0f;
165 void ffs_aconf(struct ffs *ffs)
169 void ffs_globinit(void)