Final set of changes for a working ffmpeg.
[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_AUDIO3
685 /* prefer decode_audio3() if available */
686                 size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
687                 declen = avcodec_decode_audio3(
688                         avcc, (void*)((char*)outbuf+bufseek),
689                         &size, &pkt);
690 #elif HAVE_AVCODEC_DECODE_AUDIO2
691 /* prefer decode_audio2() if available */
692                 size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
693                 declen = avcodec_decode_audio2(
694                         avcc, (void*)((char*)outbuf+bufseek),
695                         &size, pkt.data, pkt.size);
696 #elif defined HAVE_AVCODEC_DECODE_AUDIO
697                 declen = avcodec_decode_audio(
698                         avcc, (void*)((char*)outbuf+bufseek),
699                         &size, pkt.data, pkt.size);
700 #else
701                 abort();
702 #endif
703
704                 if (dec > 0 && size > 0) {
705                         FFMPEG_DEBUG_AVF("pts:%lld dts:%lld psz:%d s:%d d:%d\n",
706                                          (long long int)pkt.pts,
707                                          (long long int)pkt.dts,
708                                          pkt.size, size, declen);
709                         /* Because FFMPEG_DEBUG_AVF may expand to nothing ... */
710                         SXE_SET_UNUSED(declen);
711
712                         /* memcpy(outbuf+bufseek, (char*)buffer, size); */
713                         bufseek += size;
714                 }
715
716                 FFMPEG_DEBUG_AVF("packet state: "
717                                  "pts:%lld dts:%lld psz:%d\n",
718                                  (long long int)pkt.pts,
719                                  (long long int)pkt.dts,
720                                  (int)pkt.size);
721                 av_free_packet(&pkt);
722         }
723         av_free_packet(&pkt);
724
725         FFMPEG_DEBUG_AVF("finished reading, bufseek=%ld, rf_status=%ld\n",
726                          (long int)bufseek, (long int)rf_status);
727
728         /* convert the pig */
729         size = bufseek/framesize;
730         MEDIA_SAMPLE_FORMAT_UPSAMPLE(fmt)(outbuf, outbuf, size*mtap->channels);
731
732         /* shutdown */
733         return size;
734 }
735
736 static void
737 media_ffmpeg_rewind(media_substream *mss)
738 {
739 /* rewind the stream to the first frame */
740         /* libavformat */
741         AVFormatContext *avfc;
742         AVStream *avst;
743         Lisp_Media_Stream *ms = mss->up;
744         int64_t start_time;
745         int res = 0;
746         long int si;
747
748         /* check the integrity of the media stream */
749         if (media_stream_driver(ms) != MYSELF)
750                 return;
751
752         FFMPEG_DEBUG_AVF("rewind substream 0x%lx\n",
753                          (long unsigned int)mss);
754
755         /* fetch the format context */
756         if (!(avfc = media_stream_data(ms)))
757                 return;
758
759         si = (long int)mss->substream_data;
760         avst = avfc->streams[si];
761         if ((start_time = avst->start_time) < 0) {
762                 start_time = 0;
763         }
764
765         FFMPEG_DEBUG_AVF("rewind (idx:%ld) to %lld\n",
766                          si, (long long int)start_time);
767
768         /* ... and reset the stream */
769         res = av_seek_frame(avfc, si, AV_NOPTS_VALUE, AVSEEK_FLAG_BACKWARD);
770
771         if (res >= 0) {
772                 FFMPEG_DEBUG_AVF("rewind succeeded\n");
773                 return;
774         } else {
775                 FFMPEG_DEBUG_AVF("rewind exitted with %d\n", res);
776                 return;
777         }
778 }
779
780 \f
781 /* NOTE:
782  * the size must be big enough to compensate the hardware audio buffersize size
783  */
784 #define SAMPLE_ARRAY_SIZE (2*65536)
785 #define VIDEO_PICTURE_QUEUE_SIZE 1
786 #define SUBPICTURE_QUEUE_SIZE 4
787 #define AUDIO_DIFF_AVG_NB   20
788 #define SDL_AUDIO_BUFFER_SIZE 1024
789
790 #define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
791 #define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
792 #define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
793
794 #define FF_ALLOC_EVENT   0
795 #define FF_REFRESH_EVENT 1
796 #define FF_QUIT_EVENT    2
797
798 typedef struct PacketQueue {
799         AVPacketList *first_pkt, *last_pkt;
800         int nb_packets;
801         int size;
802         int abort_request;
803         struct sxe_semaphore_s sem;
804 } PacketQueue;
805
806 typedef struct VideoPicture {
807         /* presentation time stamp for this picture */
808         double pts;
809         void *bmp;
810         int width, height; /* source height & width */
811         int allocated;
812 } VideoPicture;
813
814 typedef struct SubPicture {
815         double pts; /* presentation time stamp for this picture */
816         AVSubtitle sub;
817 } SubPicture;
818
819 typedef struct VideoState {
820         void *parse_tid;
821         void *video_tid;
822         AVInputFormat *iformat;
823         int no_background;
824         int abort_request;
825         int paused;
826         int last_paused;
827         int seek_req;
828         int seek_flags;
829         int64_t seek_pos;
830         AVFormatContext *ic;
831         int dtg_active_format;
832
833         int audio_stream;
834
835         int av_sync_type;
836         double external_clock; /* external clock base */
837         int64_t external_clock_time;
838
839         double audio_clock;
840         double audio_diff_cum; /* used for AV difference average computation */
841         double audio_diff_avg_coef;
842         double audio_diff_threshold;
843         int audio_diff_avg_count;
844         AVStream *audio_st;
845         PacketQueue audioq;
846         int audio_hw_buf_size;
847         /* samples output by the codec. we reserve more space for avsync
848            compensation */
849         uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]
850         /* fixme, this is very gcc centric, what's aligned(x) in icc? */
851         __attribute__((aligned(16)));
852         unsigned int audio_buf_size; /* in bytes */
853         int audio_buf_index; /* in bytes */
854         AVPacket audio_pkt;
855         uint8_t *audio_pkt_data;
856         int audio_pkt_size;
857
858         int show_audio; /* if true, display audio samples */
859         int16_t sample_array[SAMPLE_ARRAY_SIZE];
860         int sample_array_index;
861         int last_i_start;
862
863         void *subtitle_tid;
864         int subtitle_stream;
865         int subtitle_stream_changed;
866         AVStream *subtitle_st;
867         PacketQueue subtitleq;
868         SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
869         int subpq_size, subpq_rindex, subpq_windex;
870         struct sxe_semaphore_s subpq_sem;
871
872         double frame_timer;
873         double frame_last_pts;
874         double frame_last_delay;
875         /* pts of last decoded frame / predicted pts of next decoded frame */
876         double video_clock;
877         int video_stream;
878         AVStream *video_st;
879         PacketQueue videoq;
880         /* current displayed pts (different from video_clock
881          * if frame fifos are used */
882         double video_current_pts;
883         /* time (av_gettime) at which we updated video_current_pts - used
884          * to have running video pts */
885         int64_t video_current_pts_time;
886         VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
887         int pictq_size, pictq_rindex, pictq_windex;
888         struct sxe_semaphore_s pictq_sem;
889
890         /* QETimer *video_timer; */
891         char *filename;
892         size_t filelen;
893
894         int width, height, xleft, ytop;
895 } VideoState;
896
897 /* since we have only one decoding thread, we can use a global
898    variable instead of a thread local variable */
899 AVPacket flush_pkt;
900
901 /* packet queue handling */
902 static void
903 packet_queue_init(PacketQueue *q)
904 {
905         memset(q, 0, sizeof(PacketQueue));
906         SXE_SEMAPH_INIT(&q->sem);
907 }
908
909 static void
910 packet_queue_flush(PacketQueue *q)
911 {
912         AVPacketList *pkt, *pkt1;
913
914         SXE_SEMAPH_LOCK(&q->sem);
915         for (pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
916                 pkt1 = pkt->next;
917                 av_free_packet(&pkt->pkt);
918                 av_freep(&pkt);
919         }
920         q->last_pkt = NULL;
921         q->first_pkt = NULL;
922         q->nb_packets = 0;
923         q->size = 0;
924         SXE_SEMAPH_UNLOCK(&q->sem);
925 }
926
927 static void
928 packet_queue_end(PacketQueue *q)
929 {
930         packet_queue_flush(q);
931         SXE_SEMAPH_FINI(&q->sem);
932 }
933
934 static int
935 packet_queue_put(PacketQueue *q, AVPacket *pkt)
936 {
937         AVPacketList *pkt1;
938
939         /* duplicate the packet */
940         if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
941                 return -1;
942
943         pkt1 = av_malloc(sizeof(AVPacketList));
944         if (!pkt1)
945                 return -1;
946         pkt1->pkt = *pkt;
947         pkt1->next = NULL;
948
949
950         SXE_SEMAPH_LOCK(&q->sem);
951
952         if (!q->last_pkt)
953
954                 q->first_pkt = pkt1;
955         else
956                 q->last_pkt->next = pkt1;
957         q->last_pkt = pkt1;
958         q->nb_packets++;
959         q->size += pkt1->pkt.size;
960         /* XXX: should duplicate packet data in DV case */
961         SXE_SEMAPH_SIGNAL(&q->sem);
962         SXE_SEMAPH_UNLOCK(&q->sem);
963         return 0;
964 }
965
966 static void
967 packet_queue_abort(PacketQueue *q)
968 {
969         SXE_SEMAPH_LOCK(&q->sem);
970
971         q->abort_request = 1;
972
973         SXE_SEMAPH_SIGNAL(&q->sem);
974         SXE_SEMAPH_UNLOCK(&q->sem);
975 }
976
977 /* return < 0 if aborted, 0 if no packet and > 0 if packet.  */
978 static int
979 packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
980         __attribute__((unused));
981
982 static int
983 packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
984 {
985         AVPacketList *pkt1;
986         int ret;
987
988         SXE_SEMAPH_LOCK(&q->sem);
989
990         for(;;) {
991                 if (q->abort_request) {
992                         ret = -1;
993                         break;
994                 }
995
996                 pkt1 = q->first_pkt;
997                 if (pkt1) {
998                         q->first_pkt = pkt1->next;
999                         if (!q->first_pkt)
1000                                 q->last_pkt = NULL;
1001                         q->nb_packets--;
1002                         q->size -= pkt1->pkt.size;
1003                         *pkt = pkt1->pkt;
1004                         av_free(pkt1);
1005                         ret = 1;
1006                         break;
1007                 } else if (!block) {
1008                         ret = 0;
1009                         break;
1010                 } else {
1011                         SXE_SEMAPH_WAIT(&q->sem);
1012                 }
1013         }
1014         SXE_SEMAPH_UNLOCK(&q->sem);
1015         return ret;
1016 }
1017
1018 static uint64_t global_video_pkt_pts = AV_NOPTS_VALUE;
1019
1020 static int
1021 my_get_buffer(struct AVCodecContext *c, AVFrame *pic, int flags)
1022 {
1023         int ret= avcodec_default_get_buffer2(c, pic, flags);
1024         uint64_t *pts= av_malloc(sizeof(uint64_t));
1025         *pts= global_video_pkt_pts;
1026         pic->opaque= pts;
1027         return ret;
1028 }
1029
1030 static int
1031 stream_component_open(VideoState *is, int stream_index, Lisp_Media_Stream *ms)
1032 {
1033         /* stream stuff */
1034         media_substream *mss = NULL;
1035         AVFormatContext *ic = is->ic;
1036         AVCodecContext *enc;
1037         AVCodec *codec;
1038
1039         if (stream_index < 0 || (size_t)stream_index >= ic->nb_streams) {
1040                 return -1;
1041         }
1042         enc = ic->streams[stream_index]->codec;
1043
1044         /* prepare audio output */
1045         if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
1046 #if 0
1047                 wanted_spec.freq = enc->sample_rate;
1048                 wanted_spec.format = AUDIO_S16SYS;
1049 #endif
1050                 /* hack for AC3. XXX: suppress that */
1051                 if (enc->channels > 2)
1052                         enc->channels = 2;
1053 #if 0
1054                 wanted_spec.channels = enc->channels;
1055                 wanted_spec.silence = 0;
1056                 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1057                 wanted_spec.callback = sdl_audio_callback;
1058                 wanted_spec.userdata = is;
1059 #endif
1060                 is->audio_hw_buf_size = 0 /* spec.size */;
1061         }
1062
1063         codec = avcodec_find_decoder(enc->codec_id);
1064         enc->debug_mv = 0 /* debug_mv */;
1065         enc->debug = 0 /* debug */;
1066         enc->workaround_bugs = 0 /* workaround_bugs */;
1067         enc->lowres = 0 /* lowres */;
1068         if (0 /* lowres */)
1069                 enc->flags |= CODEC_FLAG_EMU_EDGE;
1070         enc->idct_algo = FF_IDCT_AUTO; /* idct; */
1071         if (0 /* fast */)
1072                 enc->flags2 |= CODEC_FLAG2_FAST;
1073         enc->skip_frame = AVDISCARD_DEFAULT; /* skip_frame; */
1074         enc->skip_idct = AVDISCARD_DEFAULT; /* skip_idct; */
1075         enc->skip_loop_filter = AVDISCARD_DEFAULT; /* skip_loop_filter; */
1076 #if 0
1077         enc->error_resilience = FF_ER_CAREFUL; /* error_resilience; */
1078 #endif
1079         enc->error_concealment = 3; /* error_concealment; */
1080         if (1 /* thread_count */ > 1)
1081                 enc->thread_count = 1 /* thread_count */;
1082
1083         if (!codec ||
1084             avcodec_open2(enc, codec, NULL) < 0)
1085                 return -1;
1086
1087         /* create a substream */
1088         mss = make_media_substream_append(ms);
1089
1090         switch ((unsigned int)enc->codec_type) {
1091         case AVMEDIA_TYPE_AUDIO:
1092                 is->audio_stream = stream_index;
1093                 is->audio_st = ic->streams[stream_index];
1094                 is->audio_buf_size = 0;
1095                 is->audio_buf_index = 0;
1096
1097                 /* init averaging filter */
1098                 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1099                 is->audio_diff_avg_count = 0;
1100                 /* since we do not have a precise anough audio fifo fullness,
1101                    we correct audio sync only if larger than this threshold */
1102                 is->audio_diff_threshold =
1103                         2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1104
1105                 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1106                 packet_queue_init(&is->audioq);
1107
1108                 media_substream_type(mss) = MTYPE_AUDIO;
1109                 media_ffmpeg_analyse_audio(mss, is->ic, stream_index);
1110                 break;
1111         case AVMEDIA_TYPE_VIDEO:
1112                 is->video_stream = stream_index;
1113                 is->video_st = ic->streams[stream_index];
1114
1115                 is->frame_last_delay = 40e-3;
1116                 {
1117                         int64_t tmp = av_gettime();
1118                         is->frame_timer = (double)tmp / 1000000.0f;
1119                 }
1120                 is->video_current_pts_time = av_gettime();
1121
1122                 packet_queue_init(&is->videoq);
1123                 is->video_tid = 0 /* SDL_CreateThread(video_thread, is) */;
1124
1125                 enc->get_buffer2          = my_get_buffer;
1126                 media_substream_type(mss) = MTYPE_VIDEO;
1127
1128                 media_ffmpeg_analyse_video(mss, is->ic, stream_index);
1129                 break;
1130         case AVMEDIA_TYPE_SUBTITLE:
1131                 is->subtitle_stream = stream_index;
1132                 is->subtitle_st = ic->streams[stream_index];
1133                 packet_queue_init(&is->subtitleq);
1134
1135                 is->subtitle_tid = 0 /*SDL_CreateThread(subtitle_thread, is)*/;
1136                 break;
1137         default:
1138                 break;
1139         }
1140         return 0;
1141 }
1142
1143 static void
1144 stream_component_close(VideoState *is, int stream_index)
1145 {
1146         AVFormatContext *ic = is->ic;
1147         AVCodecContext *enc;
1148
1149         if (stream_index < 0 || (size_t)stream_index >= ic->nb_streams) {
1150                 return;
1151         }
1152         enc = ic->streams[stream_index]->codec;
1153
1154         switch ((unsigned int)enc->codec_type) {
1155         case AVMEDIA_TYPE_AUDIO:
1156                 packet_queue_abort(&is->audioq);
1157 #if 0
1158                 SDL_CloseAudio();
1159 #endif
1160                 packet_queue_end(&is->audioq);
1161                 break;
1162         case AVMEDIA_TYPE_VIDEO:
1163                 packet_queue_abort(&is->videoq);
1164
1165                 /* note: we also signal this mutex to make sure we deblock the
1166                    video thread in all cases */
1167                 SXE_SEMAPH_LOCK(&is->pictq_sem);
1168                 SXE_SEMAPH_SIGNAL(&is->pictq_sem);
1169                 SXE_SEMAPH_UNLOCK(&is->pictq_sem);
1170 #if 0
1171                 SDL_WaitThread(is->video_tid, NULL);
1172 #endif
1173                 packet_queue_end(&is->videoq);
1174                 break;
1175         case AVMEDIA_TYPE_SUBTITLE:
1176                 packet_queue_abort(&is->subtitleq);
1177
1178                 /* note: we also signal this mutex to make sure we deblock the
1179                    video thread in all cases */
1180                 SXE_SEMAPH_LOCK(&is->subpq_sem);
1181                 is->subtitle_stream_changed = 1;
1182
1183                 SXE_SEMAPH_SIGNAL(&is->subpq_sem);
1184                 SXE_SEMAPH_UNLOCK(&is->subpq_sem);
1185 #if 0
1186                 SDL_WaitThread(is->subtitle_tid, NULL);
1187 #endif
1188                 packet_queue_end(&is->subtitleq);
1189                 break;
1190         default:
1191                 break;
1192         }
1193
1194         avcodec_close(enc);
1195         switch ((unsigned int)enc->codec_type) {
1196         case AVMEDIA_TYPE_AUDIO:
1197                 is->audio_st = NULL;
1198                 is->audio_stream = -1;
1199                 break;
1200         case AVMEDIA_TYPE_VIDEO:
1201                 is->video_st = NULL;
1202                 is->video_stream = -1;
1203                 break;
1204         case AVMEDIA_TYPE_SUBTITLE:
1205                 is->subtitle_st = NULL;
1206                 is->subtitle_stream = -1;
1207                 break;
1208         default:
1209                 break;
1210         }
1211 }
1212
1213 static void
1214 dump_stream_info(const AVFormatContext *s)
1215 {
1216         static const char   *keys[] = {
1217                 "track", "title", "author", "copyright", "comment",
1218                 "album", "date",  "genre"
1219         };
1220         static const size_t  nkeys  = sizeof(keys)/sizeof(keys[0]);
1221         int           i      = 0;
1222         AVDictionaryEntry *curr = NULL;
1223         if (! s->metadata) {
1224                 fprintf(stderr, "No metadata\n");
1225                 return;
1226         }
1227
1228         for (i = 0; i < nkeys; ++i ) {
1229                 curr = av_dict_get(s->metadata,
1230                                    keys[i],
1231                                    curr,
1232                                    AV_DICT_IGNORE_SUFFIX);
1233                 if (curr)
1234                     fprintf(stderr, "%s: %s\n", curr->key, curr->value);
1235         }
1236 }
1237
1238 enum {
1239         AV_SYNC_AUDIO_MASTER, /* default choice */
1240         AV_SYNC_VIDEO_MASTER,
1241         AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
1242 };
1243
1244 static VideoState *
1245 stream_open(char *filename, size_t filelen)
1246 {
1247         VideoState   *is      = xnew(VideoState);
1248         AVDictionary *options = NULL;
1249         int err               = 0;
1250
1251         is->filename = filename;
1252         is->filelen = filelen;
1253         is->iformat = av_find_input_format("fmt");
1254         is->ytop = 0;
1255         is->xleft = 0;
1256
1257         /* initialise some semaphores */
1258         SXE_SEMAPH_INIT(&is->pictq_sem);
1259         SXE_SEMAPH_INIT(&is->subpq_sem);
1260
1261         is->av_sync_type = AV_SYNC_AUDIO_MASTER;
1262         is->parse_tid = 0; /* SDL_CreateThread(decode_thread, is); */
1263
1264 #if 0
1265         /* we force a pause when starting an RTSP stream */
1266         ap->initial_pause = 1;
1267
1268         ap->width = 0; /* frame_width; */
1269         ap->height= 0; /* frame_height; */
1270         ap->time_base= (AVRational){1, 25};
1271         ap->pix_fmt = PIX_FMT_NONE; /* frame_pix_fmt; */
1272 #endif
1273
1274         err = avformat_open_input(&is->ic, is->filename, is->iformat, &options);
1275         if (UNLIKELY(err < 0)) {
1276                 FFMPEG_DEBUG_AVF("Could not open \"%s\" (errno %d)\n",
1277                                  is->filename, err);
1278                 goto fail;
1279         }
1280
1281         return is;
1282
1283 fail:
1284         xfree(is);
1285         return NULL;
1286 }
1287
1288 /* main analysis function */
1289 static ms_driver_data_t
1290 new_media_ffmpeg_open(Lisp_Media_Stream *ms)
1291 {
1292         /* the final result */
1293         VideoState *vs = NULL;
1294         int err = 0, use_play = 0;
1295         int wanted_audio_stream = 0;
1296         int wanted_video_stream = 0;
1297         int video_index = -1, audio_index = -1;
1298         mkind_file_properties *mkfp = NULL;
1299         char *file;
1300         int file_len = 0;
1301
1302         /* initialise */
1303         av_register_all();
1304
1305         if (media_stream_kind(ms) != MKIND_FILE) {
1306                 return NULL;
1307         }
1308
1309         /* open the file */
1310         mkfp = media_stream_kind_properties(ms).fprops;
1311         TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
1312                            MALLOC, (file, file_len), Qnil);
1313         if (UNLIKELY((vs = stream_open(file, file_len)) == NULL)) {
1314                 media_stream_set_meths(ms, NULL);
1315                 media_stream_driver(ms) = MDRIVER_UNKNOWN;
1316                 return NULL;
1317         }
1318
1319 #ifdef CONFIG_RTSP_DEMUXER
1320         use_play = (ic->iformat == &rtsp_demuxer);
1321 #else
1322         use_play = 0;
1323 #endif
1324
1325         if (1 /* genpts */) {
1326                 vs->ic->flags |= AVFMT_FLAG_GENPTS;
1327         }
1328
1329         if (!use_play) {
1330                 err = avformat_find_stream_info(vs->ic, NULL);
1331                 if (err < 0) {
1332                         FFMPEG_DEBUG_AVF("\"%s\": "
1333                                          "could not find codec parameters\n",
1334                                          vs->filename);
1335                         goto fail;
1336                 }
1337                 /* FIXME hack,
1338                  * ffplay maybe should not use url_feof() to test for the end */
1339                 vs->ic->pb->eof_reached = 0;
1340         }
1341
1342         /* now we can begin to play (RTSP stream only) */
1343         av_read_play(vs->ic);
1344
1345         if (use_play) {
1346                 err = avformat_find_stream_info(vs->ic, NULL);
1347                 if (err < 0) {
1348                         FFMPEG_DEBUG_AVF("\"%s\": "
1349                                          "could not find codec parameters\n",
1350                                          vs->filename);
1351                         goto fail;
1352                 }
1353         }
1354
1355         for (size_t i = 0; i < vs->ic->nb_streams; i++) {
1356                 AVCodecContext *enc = vs->ic->streams[i]->codec;
1357                 switch ((unsigned int)enc->codec_type) {
1358                 case AVMEDIA_TYPE_AUDIO:
1359                         if ((audio_index < 0 || wanted_audio_stream-- > 0)) {
1360                                 audio_index = i;
1361                         }
1362                         break;
1363                 case AVMEDIA_TYPE_VIDEO:
1364                         if ((video_index < 0 || wanted_video_stream-- > 0)) {
1365                                 video_index = i;
1366                         }
1367                         break;
1368                 default:
1369                         break;
1370                 }
1371         }
1372         if (1 /* show_status */) {
1373                 av_dump_format(vs->ic, 0, vs->filename, 0);
1374                 dump_stream_info(vs->ic);
1375         }
1376
1377         /* open the streams */
1378         if (audio_index >= 0) {
1379                 stream_component_open(vs, audio_index, ms);
1380         }
1381
1382         if (video_index >= 0) {
1383                 stream_component_open(vs, video_index, ms);
1384         } else {
1385                 vs->show_audio = 1;
1386         }
1387
1388         if (vs->video_stream < 0 && vs->audio_stream < 0) {
1389                 FFMPEG_DEBUG_AVF("\"%s\": could not open codecs\n",
1390                                  vs->filename);
1391                 goto fail;
1392         }
1393
1394         /* keep the context */
1395         media_stream_data(ms) = vs;
1396         /* set me as driver indicator */
1397         media_stream_driver(ms) = MYSELF;
1398
1399         return vs;
1400
1401 fail:
1402         xfree(vs);
1403         return NULL;
1404 }
1405
1406 static size_t
1407 new_media_ffmpeg_read(media_substream *mss, void *outbuf, size_t length)
1408 {
1409         VideoState *is = media_stream_data(mss->up); /* was arg */
1410         int ret;
1411         AVPacket pkt1, *pkt = &pkt1;
1412 #if 0
1413         /* stuff normally set on the command line */
1414         int64_t start_time = AV_NOPTS_VALUE;
1415 #endif
1416         av_init_packet(&flush_pkt);
1417         FFMPEG_CRITICAL("read\n");
1418
1419 #if 0
1420         /* if seeking requested, we execute it */
1421         if (start_time != AV_NOPTS_VALUE) {
1422                 int64_t timestamp;
1423
1424                 timestamp = start_time;
1425                 /* add the stream start time */
1426                 if (ic->start_time != AV_NOPTS_VALUE)
1427                         timestamp += ic->start_time;
1428                 ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
1429                 if (ret < 0) {
1430                         fprintf(stderr, "%s: could not seek to position %0.3f\n",
1431                                 is->filename, (double)timestamp / AV_TIME_BASE);
1432                 }
1433         }
1434 #endif
1435
1436         for(;;) {
1437                 if (is->abort_request) {
1438                         FFMPEG_DEBUG_AVF("\n");
1439                         break;
1440                 }
1441                 if (is->paused != is->last_paused) {
1442                         is->last_paused = is->paused;
1443                         if (is->paused)
1444                                 av_read_pause(is->ic);
1445                         else
1446                                 av_read_play(is->ic);
1447                 }
1448 #ifdef CONFIG_RTSP_DEMUXER
1449                 if (is->paused && is->ic->iformat == &rtsp_demuxer) {
1450                         /* wait 10 ms to avoid trying to get another packet */
1451                         /* XXX: horrible */
1452                         SDL_Delay(10);
1453                         continue;
1454                 }
1455 #endif
1456                 if (is->seek_req) {
1457                         int stream_index= -1;
1458                         int64_t seek_target= is->seek_pos;
1459
1460                         if (is->video_stream >= 0)
1461                                 stream_index = is->video_stream;
1462                         else if (is->audio_stream >= 0)
1463                                 stream_index = is->audio_stream;
1464                         else if (is->subtitle_stream >= 0)
1465                                 stream_index = is->subtitle_stream;
1466
1467                         if (stream_index >= 0) {
1468                                 seek_target = av_rescale_q(
1469                                         seek_target, AV_TIME_BASE_Q,
1470                                         is->ic->streams[stream_index]->
1471                                         time_base);
1472                         }
1473
1474                         ret = av_seek_frame(is->ic, stream_index,
1475                                             seek_target, is->seek_flags);
1476                         if (ret < 0) {
1477                                 FFMPEG_DEBUG_AVS("\"%s: \""
1478                                                  "error while seeking\n",
1479                                                  is->ic->filename);
1480                         } else {
1481                                 if (is->audio_stream >= 0) {
1482                                         packet_queue_flush(&is->audioq);
1483                                         packet_queue_put(&is->audioq, &flush_pkt);
1484                                 }
1485                                 if (is->subtitle_stream >= 0) {
1486                                         packet_queue_flush(&is->subtitleq);
1487                                         packet_queue_put(&is->subtitleq, &flush_pkt);
1488                                 }
1489                                 if (is->video_stream >= 0) {
1490                                         packet_queue_flush(&is->videoq);
1491                                         packet_queue_put(&is->videoq, &flush_pkt);
1492                                 }
1493                         }
1494                         is->seek_req = 0;
1495                 }
1496
1497                 /* if the queue are full, no need to read more */
1498                 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
1499                     is->videoq.size > MAX_VIDEOQ_SIZE ||
1500                     is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
1501                     avio_feof(is->ic->pb)) {
1502                         /* wait 10 ms */
1503                         usleep(10);
1504                         continue;
1505                 }
1506                 ret = av_read_frame(is->ic, pkt);
1507                 if (ret < 0) {
1508                         if (is->ic->pb->error == 0) {
1509                                 usleep(100); /* wait for user event */
1510                                 continue;
1511                         } else
1512                                 break;
1513                 }
1514                 if (pkt->stream_index == is->audio_stream) {
1515                         packet_queue_put(&is->audioq, pkt);
1516                 } else if (pkt->stream_index == is->video_stream) {
1517                         packet_queue_put(&is->videoq, pkt);
1518                 } else if (pkt->stream_index == is->subtitle_stream) {
1519                         packet_queue_put(&is->subtitleq, pkt);
1520                 } else {
1521                         av_free_packet(pkt);
1522                 }
1523         }
1524         /* wait until the end */
1525         while (!is->abort_request) {
1526                 usleep(100);
1527         }
1528
1529         ret = 0;
1530
1531         /* close each stream */
1532         if (is->audio_stream >= 0)
1533                 stream_component_close(is, is->audio_stream);
1534         if (is->video_stream >= 0)
1535                 stream_component_close(is, is->video_stream);
1536         if (is->subtitle_stream >= 0)
1537                 stream_component_close(is, is->subtitle_stream);
1538         if (is->ic) {
1539                 avformat_close_input(&is->ic);
1540                 is->ic = NULL; /* safety */
1541         }
1542
1543 #if 0
1544         url_set_interrupt_cb(NULL);
1545 #endif
1546
1547         if (ret != 0) {
1548 #if 0
1549                 SDL_Event event;
1550
1551                 event.type = FF_QUIT_EVENT;
1552                 event.user.data1 = is;
1553                 SDL_PushEvent(&event);
1554 #endif
1555         }
1556         return 0;
1557 }
1558
1559 static void
1560 new_media_ffmpeg_rewind(media_substream *mss)
1561 {
1562 /* rewind the stream to the first frame */
1563         /* libavformat */
1564         AVFormatContext *avfc;
1565         AVStream *avst;
1566         Lisp_Media_Stream *ms = mss->up;
1567         int64_t start_time;
1568         int res = 0;
1569         long int si;
1570
1571         /* check the integrity of the media stream */
1572         if (media_stream_driver(ms) != MYSELF)
1573                 return;
1574
1575         FFMPEG_DEBUG_AVF("rewind substream 0x%lx\n",
1576                          (long unsigned int)mss);
1577
1578         /* fetch the format context */
1579         if (!(avfc = media_stream_data(ms)))
1580                 return;
1581
1582         si = (long int)mss->substream_data;
1583         avst = avfc->streams[si];
1584         if ((start_time = avst->start_time) < 0) {
1585                 start_time = 0;
1586         }
1587
1588         FFMPEG_DEBUG_AVF("rewind (idx:%ld) to %lld\n",
1589                          si, (long long int)start_time);
1590
1591         /* ... and reset the stream */
1592         res = av_seek_frame(avfc, -1, start_time, AVSEEK_FLAG_BACKWARD);
1593
1594         if (res >= 0) {
1595                 FFMPEG_DEBUG_AVF("rewind succeeded\n");
1596                 return;
1597         } else {
1598                 FFMPEG_DEBUG_AVF("rewind exitted with %d\n", res);
1599                 return;
1600         }
1601 }
1602
1603 \f
1604 Lisp_Object
1605 media_ffmpeg_available_formats(void)
1606 {
1607         Lisp_Object formats;
1608         AVInputFormat *avif = NULL;
1609
1610         formats = Qnil;
1611
1612         av_register_all();
1613         avif = av_iformat_next(avif);
1614
1615         while (avif) {
1616                 if (avif->name) {
1617                         const Lisp_Object fmtname =
1618                                 Fintern(build_string(avif->name), Qnil);
1619                         formats = Fcons(fmtname, formats);
1620                 }
1621                 avif = av_iformat_next(avif);
1622         }
1623
1624         return formats;
1625 }
1626
1627 #undef MYSELF