Use new virtual IO api
[sxemacs] / src / media / media-ffmpeg.c
1 /* media-ffmpeg.c - analyse audio files or streams via ffmpeg
2
3    Copyright (C) 2006 Sebastian Freundt
4
5 This file is part of SXEmacs
6
7 SXEmacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 SXEmacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
19
20
21 /* Synched up with: Not in FSF. */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include "lisp.h"
28
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <stdio.h>
32 #include <errno.h>
33 #include <string.h>
34 #if defined HAVE_STDINT_H
35 # include <stdint.h>
36 #endif  /* HAVE_STDINT_H */
37
38 #include "buffer.h"
39 #include "sysdep.h"
40 #include "sysfile.h"
41
42 #include "media-ffmpeg.h"
43
44 static int media_ffmpeg_bitrate(AVCodecContext*);
45 static AVFormatContext *media_ffmpeg_open_file(const char*);
46 AVFormatContext *media_ffmpeg_open_data(char*, size_t);
47
48 static void media_ffmpeg_analyse_audio(media_substream*, AVFormatContext*, int);
49 static void media_ffmpeg_analyse_video(media_substream*, AVFormatContext*, int);
50
51 #define MYSELF MDRIVER_FFMPEG
52
53 Lisp_Object Qffmpeg;
54
55 #define __FFMPEG_DEBUG__(args...)       fprintf(stderr, "FFMPEG " args)
56 #ifndef FFMPEG_DEBUG_FLAG
57 #define FFMPEG_DEBUG(args...)
58 #else
59 #define FFMPEG_DEBUG(args...)           __FFMPEG_DEBUG__(args)
60 #endif
61 #define FFMPEG_DEBUG_AVF(args...)       FFMPEG_DEBUG("[avformat]: " args)
62 #define FFMPEG_DEBUG_AVC(args...)       FFMPEG_DEBUG("[avcodec]: " args)
63 #define FFMPEG_DEBUG_AVS(args...)       FFMPEG_DEBUG("[stream]: " args)
64 #define FFMPEG_CRITICAL(args...)        __FFMPEG_DEBUG__("CRITICAL: " args)
65
66 \f
67 DECLARE_MEDIA_DRIVER_OPEN_METH(media_ffmpeg);
68 DECLARE_MEDIA_DRIVER_CLOSE_METH(media_ffmpeg);
69 DECLARE_MEDIA_DRIVER_PRINT_METH(media_ffmpeg);
70 DECLARE_MEDIA_DRIVER_READ_METH(media_ffmpeg);
71 DECLARE_MEDIA_DRIVER_REWIND_METH(media_ffmpeg);
72
73 DEFINE_MEDIA_DRIVER_CUSTOM(media_ffmpeg,
74                            media_ffmpeg_open, media_ffmpeg_close,
75                            media_ffmpeg_print, NULL,
76                            media_ffmpeg_read, NULL,
77                            media_ffmpeg_rewind, NULL);
78
79 DECLARE_MEDIA_DRIVER_OPEN_METH(new_media_ffmpeg);
80 DECLARE_MEDIA_DRIVER_READ_METH(new_media_ffmpeg);
81 DECLARE_MEDIA_DRIVER_REWIND_METH(new_media_ffmpeg);
82
83 DEFINE_MEDIA_DRIVER_CUSTOM(new_media_ffmpeg,
84                            new_media_ffmpeg_open, NULL,
85                            NULL, NULL,
86                            new_media_ffmpeg_read, NULL,
87                            new_media_ffmpeg_rewind, NULL);
88
89 \f
90 static int
91 media_ffmpeg_bitrate(AVCodecContext *enc)
92 {
93         int bitrate;
94
95         /* for PCM codecs, compute bitrate directly */
96         switch ((unsigned int)enc->codec_id) {
97         case CODEC_ID_PCM_S32LE:
98         case CODEC_ID_PCM_S32BE:
99         case CODEC_ID_PCM_U32LE:
100         case CODEC_ID_PCM_U32BE:
101                 bitrate = enc->sample_rate * enc->channels * 32;
102                 break;
103         case CODEC_ID_PCM_S24LE:
104         case CODEC_ID_PCM_S24BE:
105         case CODEC_ID_PCM_U24LE:
106         case CODEC_ID_PCM_U24BE:
107         case CODEC_ID_PCM_S24DAUD:
108                 bitrate = enc->sample_rate * enc->channels * 24;
109                 break;
110         case CODEC_ID_PCM_S16LE:
111         case CODEC_ID_PCM_S16BE:
112         case CODEC_ID_PCM_U16LE:
113         case CODEC_ID_PCM_U16BE:
114                 bitrate = enc->sample_rate * enc->channels * 16;
115                 break;
116         case CODEC_ID_PCM_S8:
117         case CODEC_ID_PCM_U8:
118         case CODEC_ID_PCM_ALAW:
119         case CODEC_ID_PCM_MULAW:
120                 bitrate = enc->sample_rate * enc->channels * 8;
121                 break;
122         default:
123                 bitrate = enc->bit_rate;
124                 break;
125         }
126         return bitrate;
127 }
128
129 char *media_ffmpeg_streaminfo(Lisp_Media_Stream *ms)
130 {
131         AVFormatContext   *avfc   = NULL;
132         AVDictionaryEntry *curr   = NULL;
133         char              *out    = NULL;
134         int chars_left            = 4095;
135
136         avfc = media_stream_data(ms);
137         out = xmalloc_atomic(chars_left+1);
138         if (! out)
139                 return out;
140
141         out[0]          = '\0';
142         out[chars_left] = '\0';
143
144         /* cannot use ffmpeg on corrupt streams */
145         if (media_stream_driver(ms) != MYSELF || avfc == NULL)
146                 return out;
147         
148         if (! avfc->metadata)
149                 return out;
150
151         {
152                 static const char   *keys[] = { "author", "title", "date" };
153                 static const size_t  nkeys  = sizeof(keys)/sizeof(keys[0]);
154                 int           i      = 0;
155
156                 for (i = 0; i < nkeys; ++i ) {
157                         curr = av_dict_get(avfc->metadata,
158                                            keys[i],
159                                            curr,
160                                            AV_DICT_IGNORE_SUFFIX);
161                         if (! curr)
162                                 continue;
163
164                         strncat(out, " :", chars_left);
165                         chars_left -= 2;
166                         if (chars_left < 0)
167                                 break;
168
169                         strncat(out, curr->key, chars_left);
170                         chars_left -= strlen(curr->key);
171                         if (chars_left < 0)
172                                 break;
173
174                         strncat(out, " \"", chars_left);
175                         chars_left -= 2;
176                         if (chars_left < 0)
177                                 break;
178
179                         strncat(out, curr->value, chars_left);
180                         chars_left -= strlen(curr->value);
181                         if (chars_left < 0)
182                                 break;
183
184                         strncat(out, "\"", chars_left);
185                         chars_left -= 1;
186                         if (chars_left < 0)
187                                 break;
188                 }
189         }
190
191         return out;
192 }
193
194 static void
195 media_ffmpeg_print(Lisp_Object ms, Lisp_Object pcfun, int ef)
196 {
197         return;
198 }
199
200 static AVFormatContext*
201 media_ffmpeg_open_file(const char *file)
202 {
203         AVFormatContext *avfc = NULL;
204
205         /* open the file */
206         if (avformat_open_input(&avfc, file, NULL, NULL) < 0) {
207                 FFMPEG_DEBUG_AVF("opening file failed.\n");
208                 return NULL;
209         }
210
211         /* Retrieve stream information */
212         if (avformat_find_stream_info(avfc, NULL) < 0) {
213                 FFMPEG_DEBUG_AVS("opening stream inside file failed.\n");
214                 avformat_close_input(&avfc);
215                 return NULL;
216         }
217
218         return avfc;
219 }
220
221 \f
222 static int
223 media_ffmpeg_vio_read(void *h, unsigned char *buf, int size)
224 {
225         media_data *sd = (media_data*)h;
226
227         FFMPEG_DEBUG_AVS("reading %d bytes to 0x%x, respecting seek %ld\n",
228                          size, (unsigned int)buf, sd->seek);
229
230         if ((long int)sd->length <= sd->seek) {
231                 FFMPEG_DEBUG_AVS("eof\n");
232                 return -1;
233         }
234
235         memcpy(buf, sd->data+sd->seek, size);
236         sd->seek += size;
237
238         return size;
239 }
240
241 static int64_t
242 media_ffmpeg_vio_seek(void *h, int64_t pos, int whence)
243 {
244         media_data *sd = (media_data*)h;
245
246         FFMPEG_DEBUG_AVS("seeking to %ld via %d\n", (long int)pos, whence);
247
248         switch (whence) {
249         case SEEK_SET:
250                 sd->seek = pos;
251                 break;
252         case SEEK_CUR:
253                 sd->seek = sd->seek+pos;
254                 break;
255         case SEEK_END:
256                 sd->seek = sd->length+pos;
257                 break;
258         default:
259                 /* be prolific */
260                 abort();
261         }
262         return sd->seek;
263 }
264
265 /** Size of probe buffer, for guessing file type from file contents. */
266 #define PROBE_BUF_MIN 2048
267 #define PROBE_BUF_MAX 131072
268
269 AVFormatContext*
270 media_ffmpeg_open_data(char *data, size_t size)
271 {
272         AVFormatContext *avfc    = NULL;
273         AVIOContext     *avio    = NULL;
274         media_data      *sd      = NULL;
275         unsigned char   *buffer  = NULL;
276         static const int bufsize = 65536;
277         
278         /* initialise our media_data. Note that we need to use
279          * ffmpeg's malloc because it will free it on cleaning of the
280          * context and we don't want allocators corrupting each other.
281          */
282         sd = av_malloc(sizeof(media_data));
283         if (!sd)
284               return NULL;
285
286         sd->length = size;
287         sd->seek = 0;
288         sd->data = data;
289
290         /* allocate the buffer  */
291         buffer = av_malloc(bufsize);
292         if (!buffer)
293                 return NULL;
294
295         /* create ffmpeg avio context. Note that at this point thea
296          * AVIOContext has lifetime control of the previously
297          * allocated sd and buffer.
298          */
299         avio = avio_alloc_context(buffer,
300                                   bufsize,
301                                   0, /* No writes */
302                                   sd,
303                                   media_ffmpeg_vio_read,
304                                   NULL,
305                                   media_ffmpeg_vio_seek);
306
307         /* create format context, and make it use the avio above.
308            Note that at this point avfc has lifetime control of avio,
309            through avformat_free_context */
310         avfc = avformat_alloc_context();
311         avfc->pb = avio;
312         avfc->flags = AVFMT_FLAG_CUSTOM_IO;
313
314         /* open the input */
315         if (avformat_open_input(&avfc, NULL, NULL, NULL) < 0) {
316                 FFMPEG_DEBUG_AVF("opening file failed.\n");
317                 /* Abundance of caution, as on failure open input
318                    should clear the context, but when it does it also
319                    sets avfc to NULL so this is safe. */
320                 avformat_free_context(avfc);
321                 return NULL;
322         }
323         
324         /* Retrieve stream information */
325         if (avformat_find_stream_info(avfc,NULL) < 0) {
326                 avformat_close_input(&avfc);
327                 return NULL;
328         }
329
330         return avfc;
331 }
332
333 static void
334 media_ffmpeg_close(ms_driver_data_t data)
335 {
336         AVFormatContext *avfc = (AVFormatContext*)data;
337         FFMPEG_DEBUG_AVF("closing AVFormatContext: 0x%lx\n",
338                          (long unsigned int)avfc);
339         if (avfc && avfc->iformat)
340                 avformat_close_input(&avfc);
341 }
342
343 static void
344 media_ffmpeg_analyse_audio(media_substream *mss, AVFormatContext *avfc, int st)
345 {
346         mtype_audio_properties *mtap;
347         const char *name = NULL;
348         const char *codec_name = NULL;
349         /* libavformat cruft */
350         AVStream *avst = NULL;
351         AVCodecContext *avcc = NULL;
352
353         /* unpack the stream and codec context from the container, again */
354         if (avfc)
355           avst = avfc->streams[st];
356         if (avst)
357           avcc = avst->codec;
358
359         /* initialise */
360         mtap = xnew_and_zero(mtype_audio_properties);
361
362         /* copy the name */
363         if (avfc && avfc->iformat)
364                 name = avfc->iformat->name;
365         if (avcc && avcc->codec)
366                 codec_name = avcc->codec->name;
367
368         mtap->name = name;
369         mtap->codec_name = codec_name;
370         if (avcc ) {
371                 mtap->channels = avcc->channels;
372                 mtap->samplerate = avcc->sample_rate;
373                 mtap->bitrate = media_ffmpeg_bitrate(avcc);
374
375                 /* samplewidth and framesize */
376                 switch (avcc->sample_fmt) {
377                 case AV_SAMPLE_FMT_U8:
378                         mtap->samplewidth = 8;
379                         mtap->framesize = mtap->channels * 1;
380                         mtap->msf = sxe_msf_U8;
381                         break;
382                 case AV_SAMPLE_FMT_S16:
383                         mtap->samplewidth = 16;
384                         mtap->framesize = mtap->channels * 2;
385                         mtap->msf = sxe_msf_S16;
386                         break;
387 #if defined AV_SAMPLE_FMT_S24
388                 case AV_SAMPLE_FMT_S24:
389                         mtap->samplewidth = 32;
390                         mtap->framesize = mtap->channels * 4;
391                         mtap->msf = sxe_msf_S24;
392                         break;
393 #endif  /* SAMPLE_FMT_S24 */
394                 case AV_SAMPLE_FMT_S32:
395                         mtap->samplewidth = 32;
396                         mtap->framesize = mtap->channels * 4;
397                         mtap->msf = sxe_msf_S32;
398                         break;
399                 case AV_SAMPLE_FMT_FLT:
400                         mtap->samplewidth = 8*sizeof(float);
401                         mtap->framesize = mtap->channels * sizeof(float);
402                         mtap->msf = sxe_msf_FLT;
403                         break;
404                 case AV_SAMPLE_FMT_NONE:
405                 default:
406                         mtap->samplewidth = 0;
407                         break;
408                 }
409         }
410         mtap->endianness = 0;
411
412         /* now assign */
413         media_substream_type_properties(mss).aprops = mtap;
414         media_substream_data(mss) = (void*)st;
415 }
416
417 static void
418 media_ffmpeg_analyse_video(media_substream *mss, AVFormatContext *avfc, int st)
419 {
420         mtype_video_properties *mtvp;
421         const char *name = NULL;
422         const char *codec_name = NULL;
423         /* libavformat cruft */
424         AVStream *avst = NULL;
425         AVCodecContext *avcc = NULL;
426
427         /* unpack the stream and codec context from the container, again */
428         if (avfc)
429           avst = avfc->streams[st];
430         if (avst)
431           avcc = avst->codec;
432
433         /* initialise */
434         mtvp = xnew_and_zero(mtype_video_properties);
435
436         /* copy the name */
437         if (avfc && avfc->iformat)
438                 name = avfc->iformat->name;
439         if (avcc && avcc->codec)
440                 codec_name = avcc->codec->name;
441
442         mtvp->name = name;
443         mtvp->codec_name = codec_name;
444         if (avcc) {
445           mtvp->bitrate = avcc->bit_rate;
446           mtvp->width = avcc->width;
447           mtvp->height = avcc->height;
448           mtvp->aspect_num = avcc->sample_aspect_ratio.num;
449           mtvp->aspect_den = avcc->sample_aspect_ratio.den;
450         }
451
452         mtvp->endianness = 0;
453
454         /* now assign */
455         media_substream_type_properties(mss).vprops = mtvp;
456         media_substream_data(mss) = (void*)st;
457 }
458
459 /* main analysis function */
460 static ms_driver_data_t
461 media_ffmpeg_open(Lisp_Media_Stream *ms)
462 {
463         /* stream stuff */
464         media_substream *mss;
465         /* libavformat stuff */
466         AVFormatContext *avfc = NULL;
467         AVStream *avst = NULL;
468         AVCodecContext *avcc = NULL;
469         AVCodec *avc = NULL;
470
471         /* initialise */
472         av_register_all();
473
474         switch (media_stream_kind(ms)) {
475         case MKIND_FILE: {
476                 mkind_file_properties *mkfp = NULL;
477                 const char *file;
478                 int file_len = 0;
479
480                 /* open the file */
481                 mkfp = media_stream_kind_properties(ms).fprops;
482                 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
483                                    ALLOCA, (file, file_len), Qnil);
484                 SXE_SET_UNUSED(file_len);
485
486                 avfc = media_ffmpeg_open_file(file);
487                 if (!avfc) {
488                         media_stream_set_meths(ms, NULL);
489                         media_stream_driver(ms) = MDRIVER_UNKNOWN;
490                         return NULL;
491                 }
492
493                 /* store the filesize */
494                 mkfp->filesize = avio_size(avfc->pb);
495                 break;
496         }
497         case MKIND_STRING: {
498                 mkind_string_properties *mksp = NULL;
499                 char *data;
500                 uint32_t size;
501
502                 /* open the file */
503                 mksp = media_stream_kind_properties(ms).sprops;
504                 data = mksp->stream_data;
505                 size = mksp->size;
506                 avfc = media_ffmpeg_open_data(data, size);
507
508                 if (!avfc) {
509                         media_stream_set_meths(ms, NULL);
510                         media_stream_driver(ms) = MDRIVER_UNKNOWN;
511                         return NULL;
512                 }
513                 break;
514         }
515         case MKIND_UNKNOWN:
516         case MKIND_FIFO:
517         case MKIND_STREAM:
518         case NUMBER_OF_MEDIA_KINDS:
519         default:
520                 break;
521         }
522
523         if (avfc)
524                 /* check if there is at least one usable stream */
525                 for (size_t st = 0; st < avfc->nb_streams; st++) {
526                         avst = avfc->streams[st];
527                         avcc = avst->codec;
528                         if (avcc &&
529                             avcc->codec_id != CODEC_ID_NONE &&
530                             avcc->codec_type != AVMEDIA_TYPE_DATA &&
531                             (avc = avcodec_find_decoder(avcc->codec_id)) &&
532                             (avc && (avcodec_open(avcc, avc) >= 0))) {
533
534                                 /* create a substream */
535                                 mss = make_media_substream_append(ms);
536
537                                 switch ((unsigned int)avcc->codec_type) {
538                                 case AVMEDIA_TYPE_VIDEO:
539                                         /* assign substream props */
540                                         media_substream_type(mss) = MTYPE_VIDEO;
541                                         media_ffmpeg_analyse_video(mss, avfc, st);
542                                         break;
543                                 case AVMEDIA_TYPE_AUDIO:
544                                         /* assign substream props */
545                                         media_substream_type(mss) = MTYPE_AUDIO;
546                                         media_ffmpeg_analyse_audio(mss, avfc, st);
547                                         /* set some stream handlers */
548                                         media_stream_set_meths(ms, media_ffmpeg);
549                                         break;
550                                 case AVMEDIA_TYPE_DATA:
551                                         media_substream_type(mss) = MTYPE_IMAGE;
552                                         break;
553                                 default:
554                                         media_substream_type(mss) = MTYPE_UNKNOWN;
555                                         break;
556                                 }
557                         }
558                 }
559
560         /* keep the format context */
561         media_stream_data(ms) = avfc;
562
563         /* set me as driver indicator */
564         media_stream_driver(ms) = MYSELF;
565
566         return avfc;
567 }
568
569 \f
570 static inline void
571 handle_packet(AVFormatContext *avfc, AVPacket *pkt)
572 {
573 #if 0
574         AVFrame picture;
575         AVStream *st;
576         int ret, got_picture;
577
578         st = avfc->streams[pkt->stream_index];
579
580         /* XXX: allocate picture correctly */
581         avcodec_get_frame_defaults(&picture);
582
583         ret = avcodec_decode_video(
584                 st->codec, &picture, &got_picture, pkt->data, pkt->size);
585
586         if (!got_picture) {
587                 /* no picture yet */
588                 goto discard_packet;
589         }
590 #endif
591
592         FFMPEG_DEBUG_AVF("got video frame\n");
593
594 #if 0                           /* not yet */
595 discard_packet:
596 #endif
597         av_free_packet(pkt);
598         return;
599 }
600
601 static size_t
602 media_ffmpeg_read(media_substream *mss, void *outbuf, size_t length)
603 {
604 /* read at most `length' frames into `outbuf' */
605 /* convert them to internal format */
606         /* stream stuff */
607         Lisp_Media_Stream *ms = mss->up;
608         mtype_audio_properties *mtap;
609         media_sample_format_t *fmt;
610         /* libavformat */
611         AVFormatContext *avfc;
612         AVStream *avst;
613         AVCodecContext *avcc;
614         AVCodec *avc;
615         AVPacket pkt;
616         /* buffering */
617         /* the size we present here, is _not_ the size we want, however
618          * ffmpeg is quite pedantic about the buffer size,
619          * we just pass the least possible value here to please him */
620         int size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
621         uint16_t framesize;
622         /* result */
623         long int bufseek = 0, si = -1;
624         int declen, dec, rf_status = 0;
625
626         /* check the integrity of the media stream */
627         if (media_stream_driver(ms) != MYSELF)
628                 return 0;
629
630         /* fetch the format context */
631         avfc = media_stream_data(ms);
632
633         if (!avfc)
634                 return 0;
635
636         si = (long int)mss->substream_data;
637         avst = avfc->streams[si];
638         avcc = avst->codec;
639         avc = avcc->codec;
640
641         /* unpack the substream */
642         if ((mtap = media_substream_type_properties(mss).aprops) == NULL) {
643                 FFMPEG_DEBUG_AVS("stream information missing. Uh Oh.\n");
644                 return 0;
645         }
646
647         /* fetch audio info */
648         framesize = mtap->framesize;
649         fmt = mtap->msf;
650
651         /* initialise the packet */
652         pkt.pts = pkt.dts = pkt.size = 0;
653         FFMPEG_DEBUG_AVF("initialised packet: "
654                          "pts:%lld dts:%lld psz:%d\n",
655                          (long long int)pkt.pts,
656                          (long long int)pkt.dts,
657                          pkt.size);
658
659         /* read a frame and decode it */
660         while ((size_t)bufseek <= length*framesize &&
661                (rf_status = av_read_frame(avfc, &pkt)) >= 0) {
662                 if (pkt.stream_index != si) {
663                         FFMPEG_DEBUG_AVF("SKIP reason: "
664                                          "sought after stream %ld, got %ld\n",
665                                          (long int)si,
666                                          (long int)pkt.stream_index);
667                         handle_packet(avfc, &pkt);
668                         continue;
669                 }
670
671                 FFMPEG_DEBUG_AVF("read frame: "
672                                  "pts:%lld dts:%lld psz:%d\n",
673                                  (long long int)pkt.pts,
674                                  (long long int)pkt.dts,
675                                  pkt.size);
676
677                 dec = pkt.size;
678                 /* decode the demuxed packet */
679 #ifdef HAVE_AVCODEC_DECODE_AUDIO2
680 /* prefer decode_audio2() if available */
681                 size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
682                 declen = avcodec_decode_audio2(
683                         avcc, (void*)((char*)outbuf+bufseek),
684                         &size, pkt.data, pkt.size);
685 #elif defined HAVE_AVCODEC_DECODE_AUDIO
686                 declen = avcodec_decode_audio(
687                         avcc, (void*)((char*)outbuf+bufseek),
688                         &size, pkt.data, pkt.size);
689 #else
690                 abort();
691 #endif
692
693                 if (dec > 0 && size > 0) {
694                         FFMPEG_DEBUG_AVF("pts:%lld dts:%lld psz:%d s:%d d:%d\n",
695                                          (long long int)pkt.pts,
696                                          (long long int)pkt.dts,
697                                          pkt.size, size, declen);
698
699                         /* memcpy(outbuf+bufseek, (char*)buffer, size); */
700                         bufseek += size;
701                 }
702
703                 FFMPEG_DEBUG_AVF("packet state: "
704                                  "pts:%lld dts:%lld psz:%d\n",
705                                  (long long int)pkt.pts,
706                                  (long long int)pkt.dts,
707                                  (int)pkt.size);
708                 av_free_packet(&pkt);
709         }
710         av_free_packet(&pkt);
711
712         FFMPEG_DEBUG_AVF("finished reading, bufseek=%ld, rf_status=%ld\n",
713                          (long int)bufseek, (long int)rf_status);
714
715         /* convert the pig */
716         size = bufseek/framesize;
717         MEDIA_SAMPLE_FORMAT_UPSAMPLE(fmt)(outbuf, outbuf, size*mtap->channels);
718
719         /* shutdown */
720         return size;
721 }
722
723 static void
724 media_ffmpeg_rewind(media_substream *mss)
725 {
726 /* rewind the stream to the first frame */
727         /* libavformat */
728         AVFormatContext *avfc;
729         AVStream *avst;
730         Lisp_Media_Stream *ms = mss->up;
731         int64_t start_time;
732         int res = 0;
733         long int si;
734
735         /* check the integrity of the media stream */
736         if (media_stream_driver(ms) != MYSELF)
737                 return;
738
739         FFMPEG_DEBUG_AVF("rewind substream 0x%lx\n",
740                          (long unsigned int)mss);
741
742         /* fetch the format context */
743         if (!(avfc = media_stream_data(ms)))
744                 return;
745
746         si = (long int)mss->substream_data;
747         avst = avfc->streams[si];
748         if ((start_time = avst->start_time) < 0) {
749                 start_time = 0;
750         }
751
752         FFMPEG_DEBUG_AVF("rewind (idx:%ld) to %lld\n",
753                          si, (long long int)start_time);
754
755         /* ... and reset the stream */
756         res = av_seek_frame(avfc, si, AV_NOPTS_VALUE, AVSEEK_FLAG_BACKWARD);
757
758         if (res >= 0) {
759                 FFMPEG_DEBUG_AVF("rewind succeeded\n");
760                 return;
761         } else {
762                 FFMPEG_DEBUG_AVF("rewind exitted with %d\n", res);
763                 return;
764         }
765 }
766
767 \f
768 /* NOTE:
769  * the size must be big enough to compensate the hardware audio buffersize size
770  */
771 #define SAMPLE_ARRAY_SIZE (2*65536)
772 #define VIDEO_PICTURE_QUEUE_SIZE 1
773 #define SUBPICTURE_QUEUE_SIZE 4
774 #define AUDIO_DIFF_AVG_NB   20
775 #define SDL_AUDIO_BUFFER_SIZE 1024
776
777 #define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
778 #define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
779 #define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
780
781 #define FF_ALLOC_EVENT   0
782 #define FF_REFRESH_EVENT 1
783 #define FF_QUIT_EVENT    2
784
785 typedef struct PacketQueue {
786         AVPacketList *first_pkt, *last_pkt;
787         int nb_packets;
788         int size;
789         int abort_request;
790         struct sxe_semaphore_s sem;
791 } PacketQueue;
792
793 typedef struct VideoPicture {
794         /* presentation time stamp for this picture */
795         double pts;
796         void *bmp;
797         int width, height; /* source height & width */
798         int allocated;
799 } VideoPicture;
800
801 typedef struct SubPicture {
802         double pts; /* presentation time stamp for this picture */
803         AVSubtitle sub;
804 } SubPicture;
805
806 typedef struct VideoState {
807         void *parse_tid;
808         void *video_tid;
809         AVInputFormat *iformat;
810         int no_background;
811         int abort_request;
812         int paused;
813         int last_paused;
814         int seek_req;
815         int seek_flags;
816         int64_t seek_pos;
817         AVFormatContext *ic;
818         int dtg_active_format;
819
820         int audio_stream;
821
822         int av_sync_type;
823         double external_clock; /* external clock base */
824         int64_t external_clock_time;
825
826         double audio_clock;
827         double audio_diff_cum; /* used for AV difference average computation */
828         double audio_diff_avg_coef;
829         double audio_diff_threshold;
830         int audio_diff_avg_count;
831         AVStream *audio_st;
832         PacketQueue audioq;
833         int audio_hw_buf_size;
834         /* samples output by the codec. we reserve more space for avsync
835            compensation */
836         uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]
837         /* fixme, this is very gcc centric, what's aligned(x) in icc? */
838         __attribute__((aligned(16)));
839         unsigned int audio_buf_size; /* in bytes */
840         int audio_buf_index; /* in bytes */
841         AVPacket audio_pkt;
842         uint8_t *audio_pkt_data;
843         int audio_pkt_size;
844
845         int show_audio; /* if true, display audio samples */
846         int16_t sample_array[SAMPLE_ARRAY_SIZE];
847         int sample_array_index;
848         int last_i_start;
849
850         void *subtitle_tid;
851         int subtitle_stream;
852         int subtitle_stream_changed;
853         AVStream *subtitle_st;
854         PacketQueue subtitleq;
855         SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
856         int subpq_size, subpq_rindex, subpq_windex;
857         struct sxe_semaphore_s subpq_sem;
858
859         double frame_timer;
860         double frame_last_pts;
861         double frame_last_delay;
862         /* pts of last decoded frame / predicted pts of next decoded frame */
863         double video_clock;
864         int video_stream;
865         AVStream *video_st;
866         PacketQueue videoq;
867         /* current displayed pts (different from video_clock
868          * if frame fifos are used */
869         double video_current_pts;
870         /* time (av_gettime) at which we updated video_current_pts - used
871          * to have running video pts */
872         int64_t video_current_pts_time;
873         VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
874         int pictq_size, pictq_rindex, pictq_windex;
875         struct sxe_semaphore_s pictq_sem;
876
877         /* QETimer *video_timer; */
878         char *filename;
879         size_t filelen;
880
881         int width, height, xleft, ytop;
882 } VideoState;
883
884 /* since we have only one decoding thread, we can use a global
885    variable instead of a thread local variable */
886 AVPacket flush_pkt;
887
888 /* packet queue handling */
889 static void
890 packet_queue_init(PacketQueue *q)
891 {
892         memset(q, 0, sizeof(PacketQueue));
893         SXE_SEMAPH_INIT(&q->sem);
894 }
895
896 static void
897 packet_queue_flush(PacketQueue *q)
898 {
899         AVPacketList *pkt, *pkt1;
900
901         SXE_SEMAPH_LOCK(&q->sem);
902         for (pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
903                 pkt1 = pkt->next;
904                 av_free_packet(&pkt->pkt);
905                 av_freep(&pkt);
906         }
907         q->last_pkt = NULL;
908         q->first_pkt = NULL;
909         q->nb_packets = 0;
910         q->size = 0;
911         SXE_SEMAPH_UNLOCK(&q->sem);
912 }
913
914 static void
915 packet_queue_end(PacketQueue *q)
916 {
917         packet_queue_flush(q);
918         SXE_SEMAPH_FINI(&q->sem);
919 }
920
921 static int
922 packet_queue_put(PacketQueue *q, AVPacket *pkt)
923 {
924         AVPacketList *pkt1;
925
926         /* duplicate the packet */
927         if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
928                 return -1;
929
930         pkt1 = av_malloc(sizeof(AVPacketList));
931         if (!pkt1)
932                 return -1;
933         pkt1->pkt = *pkt;
934         pkt1->next = NULL;
935
936
937         SXE_SEMAPH_LOCK(&q->sem);
938
939         if (!q->last_pkt)
940
941                 q->first_pkt = pkt1;
942         else
943                 q->last_pkt->next = pkt1;
944         q->last_pkt = pkt1;
945         q->nb_packets++;
946         q->size += pkt1->pkt.size;
947         /* XXX: should duplicate packet data in DV case */
948         SXE_SEMAPH_SIGNAL(&q->sem);
949         SXE_SEMAPH_UNLOCK(&q->sem);
950         return 0;
951 }
952
953 static void
954 packet_queue_abort(PacketQueue *q)
955 {
956         SXE_SEMAPH_LOCK(&q->sem);
957
958         q->abort_request = 1;
959
960         SXE_SEMAPH_SIGNAL(&q->sem);
961         SXE_SEMAPH_UNLOCK(&q->sem);
962 }
963
964 /* return < 0 if aborted, 0 if no packet and > 0 if packet.  */
965 static int
966 packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
967         __attribute__((unused));
968
969 static int
970 packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
971 {
972         AVPacketList *pkt1;
973         int ret;
974
975         SXE_SEMAPH_LOCK(&q->sem);
976
977         for(;;) {
978                 if (q->abort_request) {
979                         ret = -1;
980                         break;
981                 }
982
983                 pkt1 = q->first_pkt;
984                 if (pkt1) {
985                         q->first_pkt = pkt1->next;
986                         if (!q->first_pkt)
987                                 q->last_pkt = NULL;
988                         q->nb_packets--;
989                         q->size -= pkt1->pkt.size;
990                         *pkt = pkt1->pkt;
991                         av_free(pkt1);
992                         ret = 1;
993                         break;
994                 } else if (!block) {
995                         ret = 0;
996                         break;
997                 } else {
998                         SXE_SEMAPH_WAIT(&q->sem);
999                 }
1000         }
1001         SXE_SEMAPH_UNLOCK(&q->sem);
1002         return ret;
1003 }
1004
1005 static uint64_t global_video_pkt_pts = AV_NOPTS_VALUE;
1006
1007 static int
1008 my_get_buffer(struct AVCodecContext *c, AVFrame *pic)
1009 {
1010         int ret= avcodec_default_get_buffer(c, pic);
1011         uint64_t *pts= av_malloc(sizeof(uint64_t));
1012         *pts= global_video_pkt_pts;
1013         pic->opaque= pts;
1014         return ret;
1015 }
1016
1017 static void
1018 my_release_buffer(struct AVCodecContext *c, AVFrame *pic)
1019 {
1020         if(pic) av_freep(&pic->opaque);
1021         avcodec_default_release_buffer(c, pic);
1022 }
1023
1024
1025 static int
1026 stream_component_open(VideoState *is, int stream_index, Lisp_Media_Stream *ms)
1027 {
1028         /* stream stuff */
1029         media_substream *mss = NULL;
1030         AVFormatContext *ic = is->ic;
1031         AVCodecContext *enc;
1032         AVCodec *codec;
1033
1034         if (stream_index < 0 || (size_t)stream_index >= ic->nb_streams) {
1035                 return -1;
1036         }
1037         enc = ic->streams[stream_index]->codec;
1038
1039         /* prepare audio output */
1040         if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
1041 #if 0
1042                 wanted_spec.freq = enc->sample_rate;
1043                 wanted_spec.format = AUDIO_S16SYS;
1044 #endif
1045                 /* hack for AC3. XXX: suppress that */
1046                 if (enc->channels > 2)
1047                         enc->channels = 2;
1048 #if 0
1049                 wanted_spec.channels = enc->channels;
1050                 wanted_spec.silence = 0;
1051                 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1052                 wanted_spec.callback = sdl_audio_callback;
1053                 wanted_spec.userdata = is;
1054 #endif
1055                 is->audio_hw_buf_size = 0 /* spec.size */;
1056         }
1057
1058         codec = avcodec_find_decoder(enc->codec_id);
1059         enc->debug_mv = 0 /* debug_mv */;
1060         enc->debug = 0 /* debug */;
1061         enc->workaround_bugs = 0 /* workaround_bugs */;
1062         enc->lowres = 0 /* lowres */;
1063         if (0 /* lowres */)
1064                 enc->flags |= CODEC_FLAG_EMU_EDGE;
1065         enc->idct_algo = FF_IDCT_AUTO; /* idct; */
1066         if (0 /* fast */)
1067                 enc->flags2 |= CODEC_FLAG2_FAST;
1068         enc->skip_frame = AVDISCARD_DEFAULT; /* skip_frame; */
1069         enc->skip_idct = AVDISCARD_DEFAULT; /* skip_idct; */
1070         enc->skip_loop_filter = AVDISCARD_DEFAULT; /* skip_loop_filter; */
1071 #if 0
1072         enc->error_resilience = FF_ER_CAREFUL; /* error_resilience; */
1073 #endif
1074         enc->error_concealment = 3; /* error_concealment; */
1075         if (!codec ||
1076             avcodec_open(enc, codec) < 0)
1077                 return -1;
1078         if (1 /* thread_count */ > 1)
1079                 avcodec_thread_init(enc, 1 /*thread_count*/);
1080         enc->thread_count= 1 /* thread_count */;
1081
1082         /* create a substream */
1083         mss = make_media_substream_append(ms);
1084
1085         switch ((unsigned int)enc->codec_type) {
1086         case AVMEDIA_TYPE_AUDIO:
1087                 is->audio_stream = stream_index;
1088                 is->audio_st = ic->streams[stream_index];
1089                 is->audio_buf_size = 0;
1090                 is->audio_buf_index = 0;
1091
1092                 /* init averaging filter */
1093                 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1094                 is->audio_diff_avg_count = 0;
1095                 /* since we do not have a precise anough audio fifo fullness,
1096                    we correct audio sync only if larger than this threshold */
1097                 is->audio_diff_threshold =
1098                         2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1099
1100                 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1101                 packet_queue_init(&is->audioq);
1102
1103                 media_substream_type(mss) = MTYPE_AUDIO;
1104                 media_ffmpeg_analyse_audio(mss, is->ic, stream_index);
1105                 break;
1106         case AVMEDIA_TYPE_VIDEO:
1107                 is->video_stream = stream_index;
1108                 is->video_st = ic->streams[stream_index];
1109
1110                 is->frame_last_delay = 40e-3;
1111                 {
1112                         int64_t tmp = av_gettime();
1113                         is->frame_timer = (double)tmp / 1000000.0f;
1114                 }
1115                 is->video_current_pts_time = av_gettime();
1116
1117                 packet_queue_init(&is->videoq);
1118                 is->video_tid = 0 /* SDL_CreateThread(video_thread, is) */;
1119
1120                 enc->    get_buffer=     my_get_buffer;
1121                 enc->release_buffer= my_release_buffer;
1122
1123                 media_substream_type(mss) = MTYPE_VIDEO;
1124                 media_ffmpeg_analyse_video(mss, is->ic, stream_index);
1125                 break;
1126         case AVMEDIA_TYPE_SUBTITLE:
1127                 is->subtitle_stream = stream_index;
1128                 is->subtitle_st = ic->streams[stream_index];
1129                 packet_queue_init(&is->subtitleq);
1130
1131                 is->subtitle_tid = 0 /*SDL_CreateThread(subtitle_thread, is)*/;
1132                 break;
1133         default:
1134                 break;
1135         }
1136         return 0;
1137 }
1138
1139 static void
1140 stream_component_close(VideoState *is, int stream_index)
1141 {
1142         AVFormatContext *ic = is->ic;
1143         AVCodecContext *enc;
1144
1145         if (stream_index < 0 || (size_t)stream_index >= ic->nb_streams) {
1146                 return;
1147         }
1148         enc = ic->streams[stream_index]->codec;
1149
1150         switch ((unsigned int)enc->codec_type) {
1151         case AVMEDIA_TYPE_AUDIO:
1152                 packet_queue_abort(&is->audioq);
1153 #if 0
1154                 SDL_CloseAudio();
1155 #endif
1156                 packet_queue_end(&is->audioq);
1157                 break;
1158         case AVMEDIA_TYPE_VIDEO:
1159                 packet_queue_abort(&is->videoq);
1160
1161                 /* note: we also signal this mutex to make sure we deblock the
1162                    video thread in all cases */
1163                 SXE_SEMAPH_LOCK(&is->pictq_sem);
1164                 SXE_SEMAPH_SIGNAL(&is->pictq_sem);
1165                 SXE_SEMAPH_UNLOCK(&is->pictq_sem);
1166 #if 0
1167                 SDL_WaitThread(is->video_tid, NULL);
1168 #endif
1169                 packet_queue_end(&is->videoq);
1170                 break;
1171         case AVMEDIA_TYPE_SUBTITLE:
1172                 packet_queue_abort(&is->subtitleq);
1173
1174                 /* note: we also signal this mutex to make sure we deblock the
1175                    video thread in all cases */
1176                 SXE_SEMAPH_LOCK(&is->subpq_sem);
1177                 is->subtitle_stream_changed = 1;
1178
1179                 SXE_SEMAPH_SIGNAL(&is->subpq_sem);
1180                 SXE_SEMAPH_UNLOCK(&is->subpq_sem);
1181 #if 0
1182                 SDL_WaitThread(is->subtitle_tid, NULL);
1183 #endif
1184                 packet_queue_end(&is->subtitleq);
1185                 break;
1186         default:
1187                 break;
1188         }
1189
1190         avcodec_close(enc);
1191         switch ((unsigned int)enc->codec_type) {
1192         case AVMEDIA_TYPE_AUDIO:
1193                 is->audio_st = NULL;
1194                 is->audio_stream = -1;
1195                 break;
1196         case AVMEDIA_TYPE_VIDEO:
1197                 is->video_st = NULL;
1198                 is->video_stream = -1;
1199                 break;
1200         case AVMEDIA_TYPE_SUBTITLE:
1201                 is->subtitle_st = NULL;
1202                 is->subtitle_stream = -1;
1203                 break;
1204         default:
1205                 break;
1206         }
1207 }
1208
1209 static void
1210 dump_stream_info(const AVFormatContext *s)
1211 {
1212         static const char   *keys[] = {
1213                 "track", "title", "author", "copyright", "comment",
1214                 "album", "date",  "genre"
1215         };
1216         static const size_t  nkeys  = sizeof(keys)/sizeof(keys[0]);
1217         int           i      = 0;
1218         AVDictionaryEntry *curr = NULL;
1219         if (! s->metadata) {
1220                 fprintf(stderr, "No metadata\n");
1221                 return;
1222         }
1223
1224         for (i = 0; i < nkeys; ++i ) {
1225                 curr = av_dict_get(s->metadata,
1226                                    keys[i],
1227                                    curr,
1228                                    AV_DICT_IGNORE_SUFFIX);
1229                 if (curr)
1230                     fprintf(stderr, "%s: %s\n", curr->key, curr->value);
1231         }
1232 }
1233
1234 enum {
1235         AV_SYNC_AUDIO_MASTER, /* default choice */
1236         AV_SYNC_VIDEO_MASTER,
1237         AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
1238 };
1239
1240 static VideoState *
1241 stream_open(char *filename, size_t filelen)
1242 {
1243         VideoState *is = xnew(VideoState);
1244         AVFormatParameters params, *ap = &params;
1245         int err = 0;
1246
1247         is->filename = filename;
1248         is->filelen = filelen;
1249         is->iformat = av_find_input_format("fmt");
1250         is->ytop = 0;
1251         is->xleft = 0;
1252
1253         /* initialise some semaphores */
1254         SXE_SEMAPH_INIT(&is->pictq_sem);
1255         SXE_SEMAPH_INIT(&is->subpq_sem);
1256
1257         is->av_sync_type = AV_SYNC_AUDIO_MASTER;
1258         is->parse_tid = 0; /* SDL_CreateThread(decode_thread, is); */
1259
1260         memset(ap, 0, sizeof(*ap));
1261         /* we force a pause when starting an RTSP stream */
1262         ap->initial_pause = 1;
1263
1264         ap->width = 0; /* frame_width; */
1265         ap->height= 0; /* frame_height; */
1266         ap->time_base= (AVRational){1, 25};
1267         ap->pix_fmt = PIX_FMT_NONE; /* frame_pix_fmt; */
1268
1269         err = avformat_open_input(&is->ic, is->filename, is->iformat, NULL /*ap*/);
1270         if (UNLIKELY(err < 0)) {
1271                 FFMPEG_DEBUG_AVF("Could not open \"%s\" (errno %d)\n",
1272                                  is->filename, err);
1273                 goto fail;
1274         }
1275
1276         return is;
1277
1278 fail:
1279         xfree(is);
1280         return NULL;
1281 }
1282
1283 /* main analysis function */
1284 static ms_driver_data_t
1285 new_media_ffmpeg_open(Lisp_Media_Stream *ms)
1286 {
1287         /* the final result */
1288         VideoState *vs = NULL;
1289         int err = 0, use_play = 0;
1290         int wanted_audio_stream = 0;
1291         int wanted_video_stream = 0;
1292         int video_index = -1, audio_index = -1;
1293         mkind_file_properties *mkfp = NULL;
1294         char *file;
1295         int file_len = 0;
1296
1297         /* initialise */
1298         av_register_all();
1299
1300         if (media_stream_kind(ms) != MKIND_FILE) {
1301                 return NULL;
1302         }
1303
1304         /* open the file */
1305         mkfp = media_stream_kind_properties(ms).fprops;
1306         TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
1307                            MALLOC, (file, file_len), Qnil);
1308         if (UNLIKELY((vs = stream_open(file, file_len)) == NULL)) {
1309                 media_stream_set_meths(ms, NULL);
1310                 media_stream_driver(ms) = MDRIVER_UNKNOWN;
1311                 return NULL;
1312         }
1313
1314 #ifdef CONFIG_RTSP_DEMUXER
1315         use_play = (ic->iformat == &rtsp_demuxer);
1316 #else
1317         use_play = 0;
1318 #endif
1319
1320         if (1 /* genpts */) {
1321                 vs->ic->flags |= AVFMT_FLAG_GENPTS;
1322         }
1323
1324         if (!use_play) {
1325                 err = avformat_find_stream_info(vs->ic, NULL);
1326                 if (err < 0) {
1327                         FFMPEG_DEBUG_AVF("\"%s\": "
1328                                          "could not find codec parameters\n",
1329                                          vs->filename);
1330                         goto fail;
1331                 }
1332                 /* FIXME hack,
1333                  * ffplay maybe should not use url_feof() to test for the end */
1334 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
1335                 vs->ic->pb->eof_reached = 0;
1336 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
1337                 vs->ic->pb.eof_reached = 0;
1338 #endif
1339         }
1340
1341         /* now we can begin to play (RTSP stream only) */
1342         av_read_play(vs->ic);
1343
1344         if (use_play) {
1345                 err = avformat_find_stream_info(vs->ic, NULL);
1346                 if (err < 0) {
1347                         FFMPEG_DEBUG_AVF("\"%s\": "
1348                                          "could not find codec parameters\n",
1349                                          vs->filename);
1350                         goto fail;
1351                 }
1352         }
1353
1354         for (size_t i = 0; i < vs->ic->nb_streams; i++) {
1355                 AVCodecContext *enc = vs->ic->streams[i]->codec;
1356                 switch ((unsigned int)enc->codec_type) {
1357                 case AVMEDIA_TYPE_AUDIO:
1358                         if ((audio_index < 0 || wanted_audio_stream-- > 0)) {
1359                                 audio_index = i;
1360                         }
1361                         break;
1362                 case AVMEDIA_TYPE_VIDEO:
1363                         if ((video_index < 0 || wanted_video_stream-- > 0)) {
1364                                 video_index = i;
1365                         }
1366                         break;
1367                 default:
1368                         break;
1369                 }
1370         }
1371         if (1 /* show_status */) {
1372                 av_dump_format(vs->ic, 0, vs->filename, 0);
1373                 dump_stream_info(vs->ic);
1374         }
1375
1376         /* open the streams */
1377         if (audio_index >= 0) {
1378                 stream_component_open(vs, audio_index, ms);
1379         }
1380
1381         if (video_index >= 0) {
1382                 stream_component_open(vs, video_index, ms);
1383         } else {
1384                 vs->show_audio = 1;
1385         }
1386
1387         if (vs->video_stream < 0 && vs->audio_stream < 0) {
1388                 FFMPEG_DEBUG_AVF("\"%s\": could not open codecs\n",
1389                                  vs->filename);
1390                 goto fail;
1391         }
1392
1393         /* keep the context */
1394         media_stream_data(ms) = vs;
1395         /* set me as driver indicator */
1396         media_stream_driver(ms) = MYSELF;
1397
1398         return vs;
1399
1400 fail:
1401         xfree(vs);
1402         return NULL;
1403 }
1404
1405 static size_t
1406 new_media_ffmpeg_read(media_substream *mss, void *outbuf, size_t length)
1407 {
1408         VideoState *is = media_stream_data(mss->up); /* was arg */
1409         int ret;
1410         AVPacket pkt1, *pkt = &pkt1;
1411 #if 0
1412         /* stuff normally set on the command line */
1413         int64_t start_time = AV_NOPTS_VALUE;
1414 #endif
1415         av_init_packet(&flush_pkt);
1416         FFMPEG_CRITICAL("read\n");
1417
1418 #if 0
1419         /* if seeking requested, we execute it */
1420         if (start_time != AV_NOPTS_VALUE) {
1421                 int64_t timestamp;
1422
1423                 timestamp = start_time;
1424                 /* add the stream start time */
1425                 if (ic->start_time != AV_NOPTS_VALUE)
1426                         timestamp += ic->start_time;
1427                 ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
1428                 if (ret < 0) {
1429                         fprintf(stderr, "%s: could not seek to position %0.3f\n",
1430                                 is->filename, (double)timestamp / AV_TIME_BASE);
1431                 }
1432         }
1433 #endif
1434
1435         for(;;) {
1436                 if (is->abort_request) {
1437                         FFMPEG_DEBUG_AVF("\n");
1438                         break;
1439                 }
1440                 if (is->paused != is->last_paused) {
1441                         is->last_paused = is->paused;
1442                         if (is->paused)
1443                                 av_read_pause(is->ic);
1444                         else
1445                                 av_read_play(is->ic);
1446                 }
1447 #ifdef CONFIG_RTSP_DEMUXER
1448                 if (is->paused && is->ic->iformat == &rtsp_demuxer) {
1449                         /* wait 10 ms to avoid trying to get another packet */
1450                         /* XXX: horrible */
1451                         SDL_Delay(10);
1452                         continue;
1453                 }
1454 #endif
1455                 if (is->seek_req) {
1456                         int stream_index= -1;
1457                         int64_t seek_target= is->seek_pos;
1458
1459                         if (is->video_stream >= 0)
1460                                 stream_index = is->video_stream;
1461                         else if (is->audio_stream >= 0)
1462                                 stream_index = is->audio_stream;
1463                         else if (is->subtitle_stream >= 0)
1464                                 stream_index = is->subtitle_stream;
1465
1466                         if (stream_index >= 0) {
1467                                 seek_target = av_rescale_q(
1468                                         seek_target, AV_TIME_BASE_Q,
1469                                         is->ic->streams[stream_index]->
1470                                         time_base);
1471                         }
1472
1473                         ret = av_seek_frame(is->ic, stream_index,
1474                                             seek_target, is->seek_flags);
1475                         if (ret < 0) {
1476                                 FFMPEG_DEBUG_AVS("\"%s: \""
1477                                                  "error while seeking\n",
1478                                                  is->ic->filename);
1479                         } else {
1480                                 if (is->audio_stream >= 0) {
1481                                         packet_queue_flush(&is->audioq);
1482                                         packet_queue_put(&is->audioq, &flush_pkt);
1483                                 }
1484                                 if (is->subtitle_stream >= 0) {
1485                                         packet_queue_flush(&is->subtitleq);
1486                                         packet_queue_put(&is->subtitleq, &flush_pkt);
1487                                 }
1488                                 if (is->video_stream >= 0) {
1489                                         packet_queue_flush(&is->videoq);
1490                                         packet_queue_put(&is->videoq, &flush_pkt);
1491                                 }
1492                         }
1493                         is->seek_req = 0;
1494                 }
1495
1496                 /* if the queue are full, no need to read more */
1497                 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
1498                     is->videoq.size > MAX_VIDEOQ_SIZE ||
1499                     is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
1500 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
1501                     url_feof(is->ic->pb)
1502 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
1503                     url_feof(&is->ic->pb)
1504 #endif
1505                         ) {
1506                         /* wait 10 ms */
1507                         usleep(10);
1508                         continue;
1509                 }
1510                 ret = av_read_frame(is->ic, pkt);
1511                 if (ret < 0) {
1512                         if (url_ferror(
1513 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
1514                                     is->ic->pb
1515 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
1516                                     &is->ic->pb
1517 #endif
1518                                     ) == 0) {
1519                                 usleep(100); /* wait for user event */
1520                                 continue;
1521                         } else
1522                                 break;
1523                 }
1524                 if (pkt->stream_index == is->audio_stream) {
1525                         packet_queue_put(&is->audioq, pkt);
1526                 } else if (pkt->stream_index == is->video_stream) {
1527                         packet_queue_put(&is->videoq, pkt);
1528                 } else if (pkt->stream_index == is->subtitle_stream) {
1529                         packet_queue_put(&is->subtitleq, pkt);
1530                 } else {
1531                         av_free_packet(pkt);
1532                 }
1533         }
1534         /* wait until the end */
1535         while (!is->abort_request) {
1536                 usleep(100);
1537         }
1538
1539         ret = 0;
1540
1541         /* close each stream */
1542         if (is->audio_stream >= 0)
1543                 stream_component_close(is, is->audio_stream);
1544         if (is->video_stream >= 0)
1545                 stream_component_close(is, is->video_stream);
1546         if (is->subtitle_stream >= 0)
1547                 stream_component_close(is, is->subtitle_stream);
1548         if (is->ic) {
1549                 avformat_close_input(&is->ic);
1550                 is->ic = NULL; /* safety */
1551         }
1552         url_set_interrupt_cb(NULL);
1553
1554         if (ret != 0) {
1555 #if 0
1556                 SDL_Event event;
1557
1558                 event.type = FF_QUIT_EVENT;
1559                 event.user.data1 = is;
1560                 SDL_PushEvent(&event);
1561 #endif
1562         }
1563         return 0;
1564 }
1565
1566 static void
1567 new_media_ffmpeg_rewind(media_substream *mss)
1568 {
1569 /* rewind the stream to the first frame */
1570         /* libavformat */
1571         AVFormatContext *avfc;
1572         AVStream *avst;
1573         Lisp_Media_Stream *ms = mss->up;
1574         int64_t start_time;
1575         int res = 0;
1576         long int si;
1577
1578         /* check the integrity of the media stream */
1579         if (media_stream_driver(ms) != MYSELF)
1580                 return;
1581
1582         FFMPEG_DEBUG_AVF("rewind substream 0x%lx\n",
1583                          (long unsigned int)mss);
1584
1585         /* fetch the format context */
1586         if (!(avfc = media_stream_data(ms)))
1587                 return;
1588
1589         si = (long int)mss->substream_data;
1590         avst = avfc->streams[si];
1591         if ((start_time = avst->start_time) < 0) {
1592                 start_time = 0;
1593         }
1594
1595         FFMPEG_DEBUG_AVF("rewind (idx:%ld) to %lld\n",
1596                          si, (long long int)start_time);
1597
1598         /* ... and reset the stream */
1599         res = av_seek_frame(avfc, -1, start_time, AVSEEK_FLAG_BACKWARD);
1600
1601         if (res >= 0) {
1602                 FFMPEG_DEBUG_AVF("rewind succeeded\n");
1603                 return;
1604         } else {
1605                 FFMPEG_DEBUG_AVF("rewind exitted with %d\n", res);
1606                 return;
1607         }
1608 }
1609
1610 \f
1611 Lisp_Object
1612 media_ffmpeg_available_formats(void)
1613 {
1614         Lisp_Object formats;
1615         AVInputFormat *avif;
1616
1617         formats = Qnil;
1618
1619         av_register_all();
1620         avif = first_iformat;
1621
1622         while (avif) {
1623                 if (avif->name) {
1624                         const Lisp_Object fmtname =
1625                                 Fintern(build_string(avif->name), Qnil);
1626                         formats = Fcons(fmtname, formats);
1627                 }
1628                 avif = avif->next;
1629         }
1630
1631         return formats;
1632 }
1633
1634 #undef MYSELF