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