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