ffs: use the updated api in ffmpeg 0.10
[fbff.git] / ffs.c
blob3e1f5763218b5b249d8b29ad7f5c116a320ebeb2
1 #include <fcntl.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <unistd.h>
5 #include <sys/time.h>
6 #include <libavformat/avformat.h>
7 #include <libavcodec/avcodec.h>
8 #include <libswscale/swscale.h>
9 #include "ffs.h"
11 /* ffmpeg stream */
12 struct ffs {
13 AVCodecContext *cc;
14 AVFormatContext *fc;
15 AVPacket pkt;
16 int si; /* stream index */
17 long ts; /* frame timestamp (ms) */
18 long seq; /* current position in this stream */
19 long seq_all; /* seen packets after ffs_seek() */
20 long seq_cur; /* decoded packet after ffs_seek() */
22 /* decoding video frames */
23 struct SwsContext *swsc;
24 AVFrame *dst;
25 AVFrame *tmp;
28 struct ffs *ffs_alloc(char *path, int flags)
30 struct ffs *ffs;
31 int type = flags & FFS_VIDEO ? AVMEDIA_TYPE_VIDEO : AVMEDIA_TYPE_AUDIO;
32 int idx = (flags & FFS_STRIDX) - 1;
33 AVDictionary *opt = NULL;
34 ffs = malloc(sizeof(*ffs));
35 memset(ffs, 0, sizeof(*ffs));
36 ffs->si = -1;
37 if (avformat_open_input(&ffs->fc, path, NULL, NULL))
38 goto failed;
39 if (avformat_find_stream_info(ffs->fc, NULL) < 0)
40 goto failed;
41 ffs->si = av_find_best_stream(ffs->fc, type, idx, -1, NULL, 0);
42 if (ffs->si < 0)
43 goto failed;
44 ffs->cc = ffs->fc->streams[ffs->si]->codec;
45 if (avcodec_open2(ffs->cc, avcodec_find_decoder(ffs->cc->codec_id), &opt))
46 goto failed;
47 ffs->dst = avcodec_alloc_frame();
48 return ffs;
49 failed:
50 ffs_free(ffs);
51 return NULL;
54 void ffs_free(struct ffs *ffs)
56 if (ffs->swsc)
57 sws_freeContext(ffs->swsc);
58 if (ffs->dst)
59 av_free(ffs->dst);
60 if (ffs->tmp)
61 av_free(ffs->tmp);
62 if (ffs->cc)
63 avcodec_close(ffs->cc);
64 if (ffs->fc)
65 avformat_close_input(&ffs->fc);
66 free(ffs);
69 static AVPacket *ffs_pkt(struct ffs *ffs)
71 AVPacket *pkt = &ffs->pkt;
72 while (av_read_frame(ffs->fc, pkt) >= 0) {
73 ffs->seq_all++;
74 if (pkt->stream_index == ffs->si) {
75 ffs->seq_cur++;
76 ffs->seq++;
77 return pkt;
79 av_free_packet(pkt);
81 return NULL;
84 static long ts_ms(void)
86 struct timeval tv;
87 gettimeofday(&tv, NULL);
88 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
91 static int wait(long ts, int vdelay)
93 long nts = ts_ms();
94 if (nts > ts && ts + vdelay > nts) {
95 usleep((ts + vdelay - nts) * 1000);
96 return 0;
98 return 1;
101 #define MAX(a, b) ((a) < (b) ? (b) : (a))
103 void ffs_wait(struct ffs *ffs)
105 AVRational *r = &ffs->fc->streams[ffs->si]->r_frame_rate;
106 int vdelay = 1000 * r->den / r->num;
107 if (!wait(ffs->ts, MAX(vdelay, 20)))
108 ffs->ts += MAX(vdelay, 20);
109 else
110 ffs->ts = ts_ms(); /* out of sync */
113 /* audio/video frame offset difference */
114 int ffs_avdiff(struct ffs *ffs, struct ffs *affs)
116 return affs->seq_all - ffs->seq_all;
119 long ffs_pos(struct ffs *ffs, int diff)
121 return (ffs->si << 28) | (ffs->seq + diff);
124 void ffs_seek(struct ffs *ffs, long pos, int perframe)
126 long idx = pos >> 28;
127 long seq = pos & 0x00ffffff;
128 av_seek_frame(ffs->fc, idx, seq * perframe,
129 perframe == 1 ? AVSEEK_FLAG_FRAME : 0);
130 ffs->seq = seq;
131 ffs->seq_all = 0;
132 ffs->seq_cur = 0;
133 ffs->ts = 0;
136 void ffs_vinfo(struct ffs *ffs, int *w, int *h)
138 *h = ffs->cc->height;
139 *w = ffs->cc->width;
142 void ffs_ainfo(struct ffs *ffs, int *rate, int *bps, int *ch)
144 *rate = ffs->cc->sample_rate;
145 *ch = ffs->cc->channels;
146 *bps = 16;
149 int ffs_vdec(struct ffs *ffs, void **buf)
151 AVCodecContext *vcc = ffs->cc;
152 AVPacket *pkt = ffs_pkt(ffs);
153 int fine = 0;
154 if (!pkt)
155 return -1;
156 avcodec_decode_video2(vcc, ffs->tmp, &fine, pkt);
157 av_free_packet(pkt);
158 if (fine && buf) {
159 sws_scale(ffs->swsc, (void *) ffs->tmp->data, ffs->tmp->linesize,
160 0, vcc->height, ffs->dst->data, ffs->dst->linesize);
161 *buf = (void *) ffs->dst->data[0];
162 return ffs->dst->linesize[0];
164 return 0;
167 int ffs_adec(struct ffs *ffs, void *buf, int blen)
169 int len, got;
170 int rdec = 0;
171 AVPacket tmppkt = {0};
172 AVPacket *pkt = ffs_pkt(ffs);
173 if (!pkt)
174 return -1;
175 tmppkt.size = pkt->size;
176 tmppkt.data = pkt->data;
177 while (tmppkt.size > 0) {
178 len = avcodec_decode_audio4(ffs->cc, ffs->dst, &got, &tmppkt);
179 if (len < 0)
180 break;
181 tmppkt.size -= len;
182 tmppkt.data += len;
184 av_free_packet(pkt);
185 rdec = ffs->dst->linesize[0];
186 memcpy(buf, ffs->dst->data[0], rdec);
187 return rdec;
190 static int fbm2pixfmt(int fbm)
192 switch (fbm & 0x0fff) {
193 case 0x888:
194 return PIX_FMT_RGB32;
195 case 0x565:
196 return PIX_FMT_RGB565;
197 case 0x233:
198 return PIX_FMT_RGB8;
199 default:
200 fprintf(stderr, "ffs: unknown fb_mode()\n");
201 return PIX_FMT_RGB32;
205 void ffs_vsetup(struct ffs *ffs, float zoom, int fbm)
207 int h = ffs->cc->height;
208 int w = ffs->cc->width;
209 int fmt = ffs->cc->pix_fmt;
210 int pixfmt = fbm2pixfmt(fbm);
211 uint8_t *buf = NULL;
212 int n;
213 ffs->swsc = sws_getContext(w, h, fmt, w * zoom, h * zoom,
214 pixfmt, SWS_FAST_BILINEAR | SWS_CPU_CAPS_MMX2,
215 NULL, NULL, NULL);
216 ffs->tmp = avcodec_alloc_frame();
217 n = avpicture_get_size(pixfmt, w * zoom, h * zoom);
218 buf = av_malloc(n * sizeof(uint8_t));
219 avpicture_fill((AVPicture *) ffs->dst, buf, pixfmt, w * zoom, h * zoom);
222 void ffs_globinit(void)
224 av_register_all();
225 avformat_network_init();