6 #include <libavcodec/avcodec.h>
7 #include <libavformat/avformat.h>
8 #include <libswresample/swresample.h>
9 #include <libswscale/swscale.h>
12 #define FFS_SAMPLEFMT AV_SAMPLE_FMT_S16
13 #define FFS_CHLAYOUT AV_CH_LAYOUT_STEREO
15 #define MAX(a, b) ((a) < (b) ? (b) : (a))
16 #define MIN(a, b) ((a) < (b) ? (a) : (b))
24 int si
; /* stream index */
25 long ts
; /* frame timestamp (ms) */
26 long pts
; /* last decoded packet pts in milliseconds */
27 long dur
; /* last decoded packet duration */
29 /* decoding video frames */
30 struct SwsContext
*swsc
;
31 struct SwrContext
*swrc
;
36 static int ffs_stype(int flags
)
38 if (flags
& FFS_VIDEO
)
39 return AVMEDIA_TYPE_VIDEO
;
40 if (flags
& FFS_AUDIO
)
41 return AVMEDIA_TYPE_AUDIO
;
42 if (flags
& FFS_SUBTS
)
43 return AVMEDIA_TYPE_SUBTITLE
;
47 struct ffs
*ffs_alloc(char *path
, int flags
)
50 int idx
= (flags
& FFS_STRIDX
) - 1;
51 AVDictionary
*opt
= NULL
;
52 ffs
= malloc(sizeof(*ffs
));
53 memset(ffs
, 0, sizeof(*ffs
));
55 if (avformat_open_input(&ffs
->fc
, path
, NULL
, NULL
))
57 if (avformat_find_stream_info(ffs
->fc
, NULL
) < 0)
59 ffs
->si
= av_find_best_stream(ffs
->fc
, ffs_stype(flags
), idx
, -1, NULL
, 0);
62 ffs
->cc
= ffs
->fc
->streams
[ffs
->si
]->codec
;
63 if (avcodec_open2(ffs
->cc
, avcodec_find_decoder(ffs
->cc
->codec_id
), &opt
))
65 ffs
->st
= ffs
->fc
->streams
[ffs
->si
];
66 ffs
->tmp
= av_frame_alloc();
67 ffs
->dst
= av_frame_alloc();
74 void ffs_free(struct ffs
*ffs
)
79 sws_freeContext(ffs
->swsc
);
85 avcodec_close(ffs
->cc
);
87 avformat_close_input(&ffs
->fc
);
91 static AVPacket
*ffs_pkt(struct ffs
*ffs
)
93 AVPacket
*pkt
= &ffs
->pkt
;
94 while (av_read_frame(ffs
->fc
, pkt
) >= 0) {
95 if (pkt
->stream_index
== ffs
->si
) {
96 long pts
= (pkt
->dts
== AV_NOPTS_VALUE
? 0 : pkt
->dts
) *
97 av_q2d(ffs
->st
->time_base
) * 1000;
98 ffs
->dur
= MIN(MAX(0, pts
- ffs
->pts
), 1000);
99 if (pts
> ffs
->pts
|| pts
+ 200 < ffs
->pts
)
108 static long ts_ms(void)
111 gettimeofday(&tv
, NULL
);
112 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
115 static int wait(long ts
, int vdelay
)
118 if (nts
> ts
&& ts
+ vdelay
> nts
) {
119 usleep((ts
+ vdelay
- nts
) * 1000);
125 void ffs_wait(struct ffs
*ffs
)
127 int vdelay
= ffs
->dur
;
128 if (!wait(ffs
->ts
, MAX(vdelay
, 20)))
129 ffs
->ts
+= MAX(vdelay
, 20);
131 ffs
->ts
= ts_ms(); /* out of sync */
134 /* audio/video frame offset difference */
135 int ffs_avdiff(struct ffs
*ffs
, struct ffs
*affs
)
137 return affs
->pts
- ffs
->pts
;
140 long ffs_pos(struct ffs
*ffs
)
145 void ffs_seek(struct ffs
*ffs
, struct ffs
*vffs
, long pos
)
147 av_seek_frame(ffs
->fc
, vffs
->si
,
148 pos
/ av_q2d(vffs
->st
->time_base
) / 1000, 0);
152 void ffs_vinfo(struct ffs
*ffs
, int *w
, int *h
)
154 *h
= ffs
->cc
->height
;
158 void ffs_ainfo(struct ffs
*ffs
, int *rate
, int *bps
, int *ch
)
160 *rate
= ffs
->cc
->sample_rate
;
161 *ch
= av_get_channel_layout_nb_channels(FFS_CHLAYOUT
);
165 int ffs_vdec(struct ffs
*ffs
, void **buf
)
167 AVCodecContext
*vcc
= ffs
->cc
;
168 AVPacket
*pkt
= ffs_pkt(ffs
);
172 avcodec_decode_video2(vcc
, ffs
->tmp
, &fine
, pkt
);
175 sws_scale(ffs
->swsc
, (void *) ffs
->tmp
->data
, ffs
->tmp
->linesize
,
176 0, vcc
->height
, ffs
->dst
->data
, ffs
->dst
->linesize
);
177 *buf
= (void *) ffs
->dst
->data
[0];
178 return ffs
->dst
->linesize
[0];
183 int ffs_sdec(struct ffs
*ffs
, char *buf
, int blen
, long *beg
, long *end
)
185 AVPacket
*pkt
= ffs_pkt(ffs
);
186 AVSubtitle sub
= {0};
187 AVSubtitleRect
*rect
;
192 avcodec_decode_subtitle2(ffs
->cc
, &sub
, &fine
, pkt
);
197 rect
= sub
.num_rects
? sub
.rects
[0] : NULL
;
198 if (rect
&& rect
->text
)
199 snprintf(buf
, blen
, "%s", sub
.rects
[0]->text
);
200 if (rect
&& !rect
->text
&& rect
->ass
) {
202 for (i
= 0; s
&& i
< 9; i
++)
203 s
= strchr(s
, ',') ? strchr(s
, ',') + 1 : NULL
;
205 snprintf(buf
, blen
, "%s", s
);
207 if (strchr(buf
, '\n'))
208 *strchr(buf
, '\n') = '\0';
209 *beg
= ffs
->pts
+ sub
.start_display_time
* av_q2d(ffs
->st
->time_base
) * 1000;
210 *end
= ffs
->pts
+ sub
.end_display_time
* av_q2d(ffs
->st
->time_base
) * 1000;
211 avsubtitle_free(&sub
);
215 static int ffs_bytespersample(ffs
)
217 return av_get_bytes_per_sample(FFS_SAMPLEFMT
) *
218 av_get_channel_layout_nb_channels(FFS_CHLAYOUT
);
221 int ffs_adec(struct ffs
*ffs
, void *buf
, int blen
)
224 AVPacket tmppkt
= {0};
225 AVPacket
*pkt
= ffs_pkt(ffs
);
226 uint8_t *out
[] = {NULL
};
229 tmppkt
.size
= pkt
->size
;
230 tmppkt
.data
= pkt
->data
;
231 while (tmppkt
.size
> 0) {
233 len
= avcodec_decode_audio4(ffs
->cc
, ffs
->tmp
, &size
, &tmppkt
);
241 len
= swr_convert(ffs
->swrc
,
242 out
, (blen
- rdec
) / ffs_bytespersample(ffs
),
243 (void *) ffs
->tmp
->extended_data
, ffs
->tmp
->nb_samples
);
245 rdec
+= len
* ffs_bytespersample(ffs
);
251 static int fbm2pixfmt(int fbm
)
253 switch (fbm
& 0x0fff) {
255 return PIX_FMT_RGB32
;
257 return PIX_FMT_RGB565
;
261 fprintf(stderr
, "ffs: unknown fb_mode()\n");
262 return PIX_FMT_RGB32
;
266 void ffs_vconf(struct ffs
*ffs
, float zoom
, int fbm
)
268 int h
= ffs
->cc
->height
;
269 int w
= ffs
->cc
->width
;
270 int fmt
= ffs
->cc
->pix_fmt
;
271 int pixfmt
= fbm2pixfmt(fbm
);
274 ffs
->swsc
= sws_getContext(w
, h
, fmt
, w
* zoom
, h
* zoom
,
275 pixfmt
, SWS_FAST_BILINEAR
| SWS_CPU_CAPS_MMX2
,
277 n
= avpicture_get_size(pixfmt
, w
* zoom
, h
* zoom
);
278 buf
= av_malloc(n
* sizeof(uint8_t));
279 avpicture_fill((AVPicture
*) ffs
->dst
, buf
, pixfmt
, w
* zoom
, h
* zoom
);
282 void ffs_aconf(struct ffs
*ffs
)
285 ffs_ainfo(ffs
, &rate
, &bps
, &ch
);
286 ffs
->swrc
= swr_alloc_set_opts(NULL
,
287 FFS_CHLAYOUT
, FFS_SAMPLEFMT
, rate
,
288 ffs
->cc
->channel_layout
, ffs
->cc
->sample_fmt
, ffs
->cc
->sample_rate
,
293 void ffs_globinit(void)
296 avformat_network_init();
299 long ffs_duration(struct ffs
*ffs
)
301 if (ffs
->st
->duration
!= AV_NOPTS_VALUE
)
302 return ffs
->st
->duration
* av_q2d(ffs
->st
->time_base
) * 1000;
303 if (ffs
->fc
->duration
> 0)
304 return ffs
->fc
->duration
/ (AV_TIME_BASE
/ 1000);