fbff: close the oss device when fbff is paused
[fbff.git] / ffs.c
blobc7b4ec7acf31bc53fc1086ddf97a0507337c1342
1 #include <fcntl.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <unistd.h>
5 #include <sys/time.h>
6 #include <libavcodec/avcodec.h>
7 #include <libavformat/avformat.h>
8 #include <libswresample/swresample.h>
9 #include <libswscale/swscale.h>
10 #include "ffs.h"
12 #define FFS_SAMPLEFMT AV_SAMPLE_FMT_S16
13 #define FFS_CHLAYOUT AV_CH_LAYOUT_STEREO
15 /* ffmpeg stream */
16 struct ffs {
17 AVCodecContext *cc;
18 AVFormatContext *fc;
19 AVPacket pkt;
20 int si; /* stream index */
21 long ts; /* frame timestamp (ms) */
22 long seq; /* current position in this stream */
23 long seq_all; /* seen packets after ffs_seek() */
24 long seq_cur; /* decoded packet after ffs_seek() */
26 /* decoding video frames */
27 struct SwsContext *swsc;
28 struct SwrContext *swrc;
29 AVFrame *dst;
30 AVFrame *tmp;
33 struct ffs *ffs_alloc(char *path, int flags)
35 struct ffs *ffs;
36 int type = flags & FFS_VIDEO ? AVMEDIA_TYPE_VIDEO : AVMEDIA_TYPE_AUDIO;
37 int idx = (flags & FFS_STRIDX) - 1;
38 AVDictionary *opt = NULL;
39 ffs = malloc(sizeof(*ffs));
40 memset(ffs, 0, sizeof(*ffs));
41 ffs->si = -1;
42 if (avformat_open_input(&ffs->fc, path, NULL, NULL))
43 goto failed;
44 if (avformat_find_stream_info(ffs->fc, NULL) < 0)
45 goto failed;
46 ffs->si = av_find_best_stream(ffs->fc, type, idx, -1, NULL, 0);
47 if (ffs->si < 0)
48 goto failed;
49 ffs->cc = ffs->fc->streams[ffs->si]->codec;
50 if (avcodec_open2(ffs->cc, avcodec_find_decoder(ffs->cc->codec_id), &opt))
51 goto failed;
52 ffs->tmp = avcodec_alloc_frame();
53 ffs->dst = avcodec_alloc_frame();
54 return ffs;
55 failed:
56 ffs_free(ffs);
57 return NULL;
60 void ffs_free(struct ffs *ffs)
62 if (ffs->swrc)
63 swr_free(&ffs->swrc);
64 if (ffs->swsc)
65 sws_freeContext(ffs->swsc);
66 if (ffs->dst)
67 av_free(ffs->dst);
68 if (ffs->tmp)
69 av_free(ffs->tmp);
70 if (ffs->cc)
71 avcodec_close(ffs->cc);
72 if (ffs->fc)
73 avformat_close_input(&ffs->fc);
74 free(ffs);
77 static AVPacket *ffs_pkt(struct ffs *ffs)
79 AVPacket *pkt = &ffs->pkt;
80 while (av_read_frame(ffs->fc, pkt) >= 0) {
81 ffs->seq_all++;
82 if (pkt->stream_index == ffs->si) {
83 ffs->seq_cur++;
84 ffs->seq++;
85 return pkt;
87 av_free_packet(pkt);
89 return NULL;
92 static long ts_ms(void)
94 struct timeval tv;
95 gettimeofday(&tv, NULL);
96 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
99 static int wait(long ts, int vdelay)
101 long nts = ts_ms();
102 if (nts > ts && ts + vdelay > nts) {
103 usleep((ts + vdelay - nts) * 1000);
104 return 0;
106 return 1;
109 #define MAX(a, b) ((a) < (b) ? (b) : (a))
111 void ffs_wait(struct ffs *ffs)
113 AVRational *r = &ffs->fc->streams[ffs->si]->r_frame_rate;
114 int vdelay = 1000 * r->den / r->num;
115 if (!wait(ffs->ts, MAX(vdelay, 20)))
116 ffs->ts += MAX(vdelay, 20);
117 else
118 ffs->ts = ts_ms(); /* out of sync */
121 /* audio/video frame offset difference */
122 int ffs_avdiff(struct ffs *ffs, struct ffs *affs)
124 return affs->seq_all - ffs->seq_all;
127 long ffs_pos(struct ffs *ffs, int diff)
129 return (ffs->si << 28) | (ffs->seq + diff);
132 void ffs_seek(struct ffs *ffs, long pos, int perframe)
134 long idx = pos >> 28;
135 long seq = pos & 0x00ffffff;
136 av_seek_frame(ffs->fc, idx, seq * perframe,
137 perframe == 1 ? AVSEEK_FLAG_FRAME : 0);
138 ffs->seq = seq;
139 ffs->seq_all = 0;
140 ffs->seq_cur = 0;
141 ffs->ts = 0;
144 void ffs_vinfo(struct ffs *ffs, int *w, int *h)
146 *h = ffs->cc->height;
147 *w = ffs->cc->width;
150 void ffs_ainfo(struct ffs *ffs, int *rate, int *bps, int *ch)
152 *rate = ffs->cc->sample_rate;
153 *ch = av_get_channel_layout_nb_channels(FFS_CHLAYOUT);
154 *bps = 16;
157 int ffs_vdec(struct ffs *ffs, void **buf)
159 AVCodecContext *vcc = ffs->cc;
160 AVPacket *pkt = ffs_pkt(ffs);
161 int fine = 0;
162 if (!pkt)
163 return -1;
164 avcodec_decode_video2(vcc, ffs->tmp, &fine, pkt);
165 av_free_packet(pkt);
166 if (fine && buf) {
167 sws_scale(ffs->swsc, (void *) ffs->tmp->data, ffs->tmp->linesize,
168 0, vcc->height, ffs->dst->data, ffs->dst->linesize);
169 *buf = (void *) ffs->dst->data[0];
170 return ffs->dst->linesize[0];
172 return 0;
175 static int ffs_bytespersample(ffs)
177 return av_get_bytes_per_sample(FFS_SAMPLEFMT) *
178 av_get_channel_layout_nb_channels(FFS_CHLAYOUT);
181 int ffs_adec(struct ffs *ffs, void *buf, int blen)
183 int rdec = 0;
184 AVPacket tmppkt = {0};
185 AVPacket *pkt = ffs_pkt(ffs);
186 uint8_t *out[] = {NULL};
187 if (!pkt)
188 return -1;
189 tmppkt.size = pkt->size;
190 tmppkt.data = pkt->data;
191 while (tmppkt.size > 0) {
192 int len, size;
193 len = avcodec_decode_audio4(ffs->cc, ffs->tmp, &size, &tmppkt);
194 if (len < 0)
195 break;
196 tmppkt.size -= len;
197 tmppkt.data += len;
198 if (size <= 0)
199 continue;
200 out[0] = buf + rdec;
201 len = swr_convert(ffs->swrc,
202 out, (blen - rdec) / ffs_bytespersample(ffs),
203 (void *) ffs->tmp->extended_data, ffs->tmp->nb_samples);
204 if (len > 0)
205 rdec += len * ffs_bytespersample(ffs);
207 av_free_packet(pkt);
208 return rdec;
211 static int fbm2pixfmt(int fbm)
213 switch (fbm & 0x0fff) {
214 case 0x888:
215 return PIX_FMT_RGB32;
216 case 0x565:
217 return PIX_FMT_RGB565;
218 case 0x233:
219 return PIX_FMT_RGB8;
220 default:
221 fprintf(stderr, "ffs: unknown fb_mode()\n");
222 return PIX_FMT_RGB32;
226 void ffs_vconf(struct ffs *ffs, float zoom, int fbm)
228 int h = ffs->cc->height;
229 int w = ffs->cc->width;
230 int fmt = ffs->cc->pix_fmt;
231 int pixfmt = fbm2pixfmt(fbm);
232 uint8_t *buf = NULL;
233 int n;
234 ffs->swsc = sws_getContext(w, h, fmt, w * zoom, h * zoom,
235 pixfmt, SWS_FAST_BILINEAR | SWS_CPU_CAPS_MMX2,
236 NULL, NULL, NULL);
237 n = avpicture_get_size(pixfmt, w * zoom, h * zoom);
238 buf = av_malloc(n * sizeof(uint8_t));
239 avpicture_fill((AVPicture *) ffs->dst, buf, pixfmt, w * zoom, h * zoom);
242 void ffs_aconf(struct ffs *ffs)
244 int rate, bps, ch;
245 ffs_ainfo(ffs, &rate, &bps, &ch);
246 ffs->swrc = swr_alloc_set_opts(NULL,
247 FFS_CHLAYOUT, FFS_SAMPLEFMT, rate,
248 ffs->cc->channel_layout, ffs->cc->sample_fmt, ffs->cc->sample_rate,
249 0, NULL);
250 swr_init(ffs->swrc);
253 void ffs_globinit(void)
255 av_register_all();
256 avformat_network_init();