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