6 #include <libavcodec/avcodec.h>
7 #include <libavformat/avformat.h>
8 #include <libavutil/imgutils.h>
9 #include <libavutil/opt.h>
10 #include <libswresample/swresample.h>
11 #include <libswscale/swscale.h>
14 #define FFS_SAMPLEFMT AV_SAMPLE_FMT_S16
15 #define FFS_CHLAYOUT AV_CH_LAYOUT_STEREO
18 #define MAX(a, b) ((a) < (b) ? (b) : (a))
19 #define MIN(a, b) ((a) < (b) ? (a) : (b))
26 AVPacket pkt
; /* used in ffs_pkt() */
27 int si
; /* stream index */
28 long ts
; /* frame timestamp (ms) */
29 long pts
; /* last decoded packet pts in milliseconds */
30 long dur
; /* last decoded packet duration */
31 struct SwsContext
*swsc
;
32 struct SwrContext
*swrc
;
33 AVFrame
*dst
; /* used in ffs_vdec() */
34 AVFrame
*tmp
; /* used in ffs_recv() */
37 static int ffs_stype(int flags
)
39 if (flags
& FFS_VIDEO
)
40 return AVMEDIA_TYPE_VIDEO
;
41 if (flags
& FFS_AUDIO
)
42 return AVMEDIA_TYPE_AUDIO
;
43 if (flags
& FFS_SUBTS
)
44 return AVMEDIA_TYPE_SUBTITLE
;
48 struct ffs
*ffs_alloc(char *path
, int flags
)
51 int idx
= (flags
& FFS_STRIDX
) - 1;
52 AVDictionary
*opt
= NULL
;
53 const AVCodec
*dec
= NULL
;
54 ffs
= malloc(sizeof(*ffs
));
55 memset(ffs
, 0, sizeof(*ffs
));
57 if (avformat_open_input(&ffs
->fc
, path
, NULL
, NULL
))
59 if (avformat_find_stream_info(ffs
->fc
, NULL
) < 0)
61 ffs
->si
= av_find_best_stream(ffs
->fc
, ffs_stype(flags
), idx
, -1, NULL
, 0);
64 dec
= avcodec_find_decoder(ffs
->fc
->streams
[ffs
->si
]->codecpar
->codec_id
);
67 ffs
->cc
= avcodec_alloc_context3(dec
);
70 avcodec_parameters_to_context(ffs
->cc
, ffs
->fc
->streams
[ffs
->si
]->codecpar
);
71 if (avcodec_open2(ffs
->cc
, avcodec_find_decoder(ffs
->cc
->codec_id
), &opt
))
73 ffs
->st
= ffs
->fc
->streams
[ffs
->si
];
74 ffs
->tmp
= av_frame_alloc();
75 ffs
->dst
= av_frame_alloc();
82 void ffs_free(struct ffs
*ffs
)
87 sws_freeContext(ffs
->swsc
);
93 avcodec_close(ffs
->cc
);
95 avformat_close_input(&ffs
->fc
);
99 static AVPacket
*ffs_pkt(struct ffs
*ffs
)
101 AVPacket
*pkt
= &ffs
->pkt
;
102 while (av_read_frame(ffs
->fc
, pkt
) >= 0) {
103 if (pkt
->stream_index
== ffs
->si
) {
104 long pts
= (pkt
->dts
== AV_NOPTS_VALUE
? 0 : pkt
->dts
) *
105 av_q2d(ffs
->st
->time_base
) * 1000;
106 ffs
->dur
= MIN(MAX(0, pts
- ffs
->pts
), 1000);
107 if (pts
> ffs
->pts
|| pts
+ 200 < ffs
->pts
)
111 av_packet_unref(pkt
);
116 static AVFrame
*ffs_recv(struct ffs
*ffs
)
118 AVCodecContext
*vcc
= ffs
->cc
;
119 AVPacket
*pkt
= NULL
;
123 if ((ret
= avcodec_receive_frame(vcc
, ffs
->tmp
)) == 0)
125 if (ret
< 0 && ret
!= AVERROR(EAGAIN
))
127 if ((pkt
= ffs_pkt(ffs
)) == NULL
)
129 if ((ret
= avcodec_send_packet(vcc
, pkt
)) < 0) {
130 av_packet_unref(pkt
);
131 if (ret
== AVERROR(EOF
) || errcnt
++ == 3)
134 av_packet_unref(pkt
);
139 static long ts_ms(void)
142 gettimeofday(&tv
, NULL
);
143 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
146 static int wait(long ts
, int vdelay
)
149 if (nts
> ts
&& ts
+ vdelay
> nts
) {
150 usleep((ts
+ vdelay
- nts
) * 1000);
156 void ffs_wait(struct ffs
*ffs
)
158 int vdelay
= ffs
->dur
;
159 if (!wait(ffs
->ts
, MAX(vdelay
, 20)))
160 ffs
->ts
+= MAX(vdelay
, 20);
162 ffs
->ts
= ts_ms(); /* out of sync */
165 /* audio/video frame offset difference */
166 int ffs_avdiff(struct ffs
*ffs
, struct ffs
*affs
)
168 return affs
->pts
- ffs
->pts
;
171 long ffs_pos(struct ffs
*ffs
)
176 void ffs_seek(struct ffs
*ffs
, struct ffs
*vffs
, long pos
)
178 av_seek_frame(ffs
->fc
, vffs
->si
,
179 pos
/ av_q2d(vffs
->st
->time_base
) / 1000, 0);
183 void ffs_vinfo(struct ffs
*ffs
, int *w
, int *h
)
185 *h
= ffs
->cc
->height
;
189 void ffs_ainfo(struct ffs
*ffs
, int *rate
, int *bps
, int *ch
)
191 *rate
= ffs
->cc
->sample_rate
;
196 int ffs_vdec(struct ffs
*ffs
, void **buf
)
198 AVFrame
*tmp
= ffs_recv(ffs
);
199 AVFrame
*dst
= ffs
->dst
;
203 sws_scale(ffs
->swsc
, (void *) tmp
->data
, tmp
->linesize
,
204 0, ffs
->cc
->height
, dst
->data
, dst
->linesize
);
205 *buf
= (void *) dst
->data
[0];
206 return dst
->linesize
[0];
211 int ffs_sdec(struct ffs
*ffs
, char *buf
, int blen
, long *beg
, long *end
)
213 AVPacket
*pkt
= ffs_pkt(ffs
);
214 AVSubtitle sub
= {0};
215 AVSubtitleRect
*rect
;
220 avcodec_decode_subtitle2(ffs
->cc
, &sub
, &fine
, pkt
);
221 av_packet_unref(pkt
);
225 rect
= sub
.num_rects
? sub
.rects
[0] : NULL
;
226 if (rect
&& rect
->text
)
227 snprintf(buf
, blen
, "%s", sub
.rects
[0]->text
);
228 if (rect
&& !rect
->text
&& rect
->ass
) {
230 for (i
= 0; s
&& i
< 9; i
++)
231 s
= strchr(s
, ',') ? strchr(s
, ',') + 1 : NULL
;
233 snprintf(buf
, blen
, "%s", s
);
235 if (strchr(buf
, '\n'))
236 *strchr(buf
, '\n') = '\0';
237 *beg
= ffs
->pts
+ sub
.start_display_time
* av_q2d(ffs
->st
->time_base
) * 1000;
238 *end
= ffs
->pts
+ sub
.end_display_time
* av_q2d(ffs
->st
->time_base
) * 1000;
239 avsubtitle_free(&sub
);
243 static int ffs_bytespersample(struct ffs
*ffs
)
245 return av_get_bytes_per_sample(FFS_SAMPLEFMT
) * FFS_CHCNT
;
248 int ffs_adec(struct ffs
*ffs
, void *buf
, int blen
)
250 AVFrame
*tmp
= ffs_recv(ffs
);
251 uint8_t *out
[] = {buf
};
255 len
= swr_convert(ffs
->swrc
, out
, blen
/ ffs_bytespersample(ffs
),
256 (void *) tmp
->extended_data
, tmp
->nb_samples
);
257 return len
> 0 ? len
* ffs_bytespersample(ffs
) : 0;
260 static int fbm2pixfmt(int fbm
)
262 switch (fbm
& 0x0fff) {
264 return AV_PIX_FMT_RGB32
;
266 return AV_PIX_FMT_RGB565
;
268 return AV_PIX_FMT_RGB8
;
270 fprintf(stderr
, "ffs: unknown fb_mode()\n");
271 return AV_PIX_FMT_RGB32
;
275 void ffs_vconf(struct ffs
*ffs
, float zoom
, int fbm
)
277 int h
= ffs
->cc
->height
;
278 int w
= ffs
->cc
->width
;
279 int fmt
= ffs
->cc
->pix_fmt
;
280 int pixfmt
= fbm2pixfmt(fbm
);
283 ffs
->swsc
= sws_getContext(w
, h
, fmt
, w
* zoom
, h
* zoom
,
284 pixfmt
, SWS_FAST_BILINEAR
,
286 n
= av_image_get_buffer_size(pixfmt
, w
* zoom
, h
* zoom
, 8);
287 buf
= av_malloc(n
* sizeof(uint8_t));
288 av_image_fill_arrays(ffs
->dst
->data
, ffs
->dst
->linesize
, buf
,
289 pixfmt
, w
* zoom
, h
* zoom
, 8);
292 void ffs_aconf(struct ffs
*ffs
)
295 ffs_ainfo(ffs
, &rate
, &bps
, &ch
);
296 ffs
->swrc
= swr_alloc();
297 av_opt_set_int(ffs
->swrc
, "in_channel_layout", ffs
->cc
->channel_layout
, 0);
298 /* av_opt_set_int(ffs->swrc, "in_channel_layout", ffs->cc->ch_layout, 0); */
299 av_opt_set_int(ffs
->swrc
, "in_sample_rate", ffs
->cc
->sample_rate
, 0);
300 av_opt_set_sample_fmt(ffs
->swrc
, "in_sample_fmt", ffs
->cc
->sample_fmt
, 0);
301 av_opt_set_int(ffs
->swrc
, "out_channel_layout", FFS_CHLAYOUT
, 0);
302 av_opt_set_int(ffs
->swrc
, "out_sample_rate", rate
, 0);
303 av_opt_set_sample_fmt(ffs
->swrc
, "out_sample_fmt", FFS_SAMPLEFMT
, 0);
307 void ffs_globinit(void)
311 long ffs_duration(struct ffs
*ffs
)
313 if (ffs
->st
->duration
!= AV_NOPTS_VALUE
)
314 return ffs
->st
->duration
* av_q2d(ffs
->st
->time_base
) * 1000;
315 if (ffs
->fc
->duration
> 0)
316 return ffs
->fc
->duration
/ (AV_TIME_BASE
/ 1000);