1 /* media-ffmpeg.c - analyse audio files or streams via ffmpeg
3 Copyright (C) 2006 Sebastian Freundt
5 This file is part of SXEmacs
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.
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.
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/>. */
21 /* Synched up with: Not in FSF. */
34 #if defined HAVE_STDINT_H
36 #endif /* HAVE_STDINT_H */
42 #include "media-ffmpeg.h"
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);
48 static void media_ffmpeg_analyse_audio(media_substream*, AVFormatContext*, int);
49 static void media_ffmpeg_analyse_video(media_substream*, AVFormatContext*, int);
51 #define MYSELF MDRIVER_FFMPEG
55 #define __FFMPEG_DEBUG__(args...) fprintf(stderr, "FFMPEG " args)
56 #ifndef FFMPEG_DEBUG_FLAG
57 #define FFMPEG_DEBUG(args...)
59 #define FFMPEG_DEBUG(args...) __FFMPEG_DEBUG__(args)
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)
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);
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);
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);
83 DEFINE_MEDIA_DRIVER_CUSTOM(new_media_ffmpeg,
84 new_media_ffmpeg_open, NULL,
86 new_media_ffmpeg_read, NULL,
87 new_media_ffmpeg_rewind, NULL);
91 media_ffmpeg_bitrate(AVCodecContext *enc)
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;
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;
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;
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;
123 bitrate = enc->bit_rate;
129 char *media_ffmpeg_streaminfo(Lisp_Media_Stream *ms)
131 AVFormatContext *avfc = NULL;
132 AVDictionaryEntry *curr = NULL;
134 int chars_left = 4095;
136 avfc = media_stream_data(ms);
137 out = xmalloc_atomic(chars_left+1);
142 out[chars_left] = '\0';
144 /* cannot use ffmpeg on corrupt streams */
145 if (media_stream_driver(ms) != MYSELF || avfc == NULL)
148 if (! avfc->metadata)
152 static const char *keys[] = { "author", "title", "date" };
153 static const size_t nkeys = sizeof(keys)/sizeof(keys[0]);
156 for (i = 0; i < nkeys; ++i ) {
157 curr = av_dict_get(avfc->metadata,
160 AV_DICT_IGNORE_SUFFIX);
164 strncat(out, " :", chars_left);
169 strncat(out, curr->key, chars_left);
170 chars_left -= strlen(curr->key);
174 strncat(out, " \"", chars_left);
179 strncat(out, curr->value, chars_left);
180 chars_left -= strlen(curr->value);
184 strncat(out, "\"", chars_left);
195 media_ffmpeg_print(Lisp_Object ms, Lisp_Object pcfun, int ef)
200 static AVFormatContext*
201 media_ffmpeg_open_file(const char *file)
203 #if defined HAVE_AVFORMAT_ALLOC_CONTEXT
204 AVFormatContext *avfc = avformat_alloc_context();
205 #elif defined HAVE_AV_ALLOC_FORMAT_CONTEXT
206 /* deprecated already, but `people' like Horst still use this */
207 AVFormatContext *avfc = av_alloc_format_context();
209 # error "Your ffmpeg library is too old. Adopt a new one."
210 #endif /* HAVE_AVFORMAT_ALLOC_CONTEXT */
213 if (av_open_input_file(&avfc, file, NULL, 0, NULL) < 0) {
214 FFMPEG_DEBUG_AVF("opening file failed.\n");
220 /* Retrieve stream information */
221 if (av_find_stream_info(avfc) < 0) {
222 FFMPEG_DEBUG_AVS("opening stream inside file failed.\n");
223 av_close_input_file(avfc);
234 media_ffmpeg_vio_open(URLContext *h, const char *filename, int flags)
240 media_ffmpeg_vio_read(URLContext *h, unsigned char *buf, int size)
242 media_data *sd = (media_data*)h->priv_data;
244 FFMPEG_DEBUG_AVS("reading %d bytes to 0x%x, respecting seek %ld\n",
245 size, (unsigned int)buf, sd->seek);
247 if ((long int)sd->length <= sd->seek) {
248 FFMPEG_DEBUG_AVS("eof\n");
252 memcpy(buf, sd->data+sd->seek, size);
259 media_ffmpeg_vio_write(URLContext *h, unsigned char *buf, int size)
265 media_ffmpeg_vio_seek(URLContext *h, int64_t pos, int whence)
267 media_data *sd = (media_data*)h->priv_data;
269 FFMPEG_DEBUG_AVS("seeking to %ld via %d\n", (long int)pos, whence);
276 sd->seek = sd->seek+pos;
279 sd->seek = sd->length+pos;
289 media_ffmpeg_vio_close(URLContext *h)
297 /* this is a memory-i/o protocol in case we have to deal with string data */
298 static URLProtocol media_ffmpeg_protocol = {
300 media_ffmpeg_vio_open,
301 media_ffmpeg_vio_read,
302 media_ffmpeg_vio_write,
303 media_ffmpeg_vio_seek,
304 media_ffmpeg_vio_close,
307 /** Size of probe buffer, for guessing file type from file contents. */
308 #define PROBE_BUF_MIN 2048
309 #define PROBE_BUF_MAX 131072
312 media_ffmpeg_open_data(char *data, size_t size)
314 #if defined HAVE_AVFORMAT_ALLOC_CONTEXT
315 AVFormatContext *avfc = avformat_alloc_context();
316 #elif defined HAVE_AV_ALLOC_FORMAT_CONTEXT
317 /* deprecated already, but `people' like Horst still use this */
318 AVFormatContext *avfc = av_alloc_format_context();
320 # error "Your ffmpeg library is too old. Adopt a new one."
321 #endif /* HAVE_AVFORMAT_ALLOC_CONTEXT */
322 AVProbeData *pd = NULL;
323 ByteIOContext *bioctx = NULL;
324 AVInputFormat *fmt = NULL;
325 char file[] = "SXEmff:SXEmacs.mp3\000";
326 media_data *sd = NULL;
328 /* register our virtual i/o */
329 #if defined HAVE_AV_REGISTER_PROTOCOL
330 av_register_protocol(&media_ffmpeg_protocol);
331 #elif defined HAVE_REGISTER_PROTOCOL
332 register_protocol(&media_ffmpeg_protocol);
334 # error "Get a recent ffmpeg or get a life."
337 /* initialise our media_data */
338 sd = xnew_and_zero(media_data);
343 /* register ffmpeg byteio */
344 bioctx = xnew_and_zero(ByteIOContext);
345 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
346 url_fopen(&bioctx, file, URL_RDONLY);
347 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
348 url_fopen(bioctx, file, URL_RDONLY);
350 /* erm, register us at the byteio context */
351 ((URLContext*)(bioctx->opaque))->priv_data = sd;
354 pd = xnew_and_zero(AVProbeData);
359 pd->buf = (void*)sd->data;
360 pd->buf_size = PROBE_BUF_MIN;
361 fmt = av_probe_input_format(pd, 1);
363 /* if still no format found, error */
373 if (av_open_input_stream(&avfc, bioctx, file, fmt, NULL) < 0) {
381 /* Retrieve stream information */
382 if (av_find_stream_info(avfc) < 0) {
394 media_ffmpeg_close(ms_driver_data_t data)
396 AVFormatContext *avfc = (AVFormatContext*)data;
397 FFMPEG_DEBUG_AVF("closing AVFormatContext: 0x%lx\n",
398 (long unsigned int)avfc);
399 if (avfc && avfc->iformat)
400 av_close_input_file(avfc);
404 media_ffmpeg_analyse_audio(media_substream *mss, AVFormatContext *avfc, int st)
406 mtype_audio_properties *mtap;
407 const char *name = NULL;
408 const char *codec_name = NULL;
409 /* libavformat cruft */
410 AVStream *avst = NULL;
411 AVCodecContext *avcc = NULL;
413 /* unpack the stream and codec context from the container, again */
415 avst = avfc->streams[st];
420 mtap = xnew_and_zero(mtype_audio_properties);
423 if (avfc && avfc->iformat)
424 name = avfc->iformat->name;
425 if (avcc && avcc->codec)
426 codec_name = avcc->codec->name;
429 mtap->codec_name = codec_name;
431 mtap->channels = avcc->channels;
432 mtap->samplerate = avcc->sample_rate;
433 mtap->bitrate = media_ffmpeg_bitrate(avcc);
435 /* samplewidth and framesize */
436 switch (avcc->sample_fmt) {
437 case AV_SAMPLE_FMT_U8:
438 mtap->samplewidth = 8;
439 mtap->framesize = mtap->channels * 1;
440 mtap->msf = sxe_msf_U8;
442 case AV_SAMPLE_FMT_S16:
443 mtap->samplewidth = 16;
444 mtap->framesize = mtap->channels * 2;
445 mtap->msf = sxe_msf_S16;
447 #if defined AV_SAMPLE_FMT_S24
448 case AV_SAMPLE_FMT_S24:
449 mtap->samplewidth = 32;
450 mtap->framesize = mtap->channels * 4;
451 mtap->msf = sxe_msf_S24;
453 #endif /* SAMPLE_FMT_S24 */
454 case AV_SAMPLE_FMT_S32:
455 mtap->samplewidth = 32;
456 mtap->framesize = mtap->channels * 4;
457 mtap->msf = sxe_msf_S32;
459 case AV_SAMPLE_FMT_FLT:
460 mtap->samplewidth = 8*sizeof(float);
461 mtap->framesize = mtap->channels * sizeof(float);
462 mtap->msf = sxe_msf_FLT;
464 case AV_SAMPLE_FMT_NONE:
466 mtap->samplewidth = 0;
470 mtap->endianness = 0;
473 media_substream_type_properties(mss).aprops = mtap;
474 media_substream_data(mss) = (void*)st;
478 media_ffmpeg_analyse_video(media_substream *mss, AVFormatContext *avfc, int st)
480 mtype_video_properties *mtvp;
481 const char *name = NULL;
482 const char *codec_name = NULL;
483 /* libavformat cruft */
484 AVStream *avst = NULL;
485 AVCodecContext *avcc = NULL;
487 /* unpack the stream and codec context from the container, again */
489 avst = avfc->streams[st];
494 mtvp = xnew_and_zero(mtype_video_properties);
497 if (avfc && avfc->iformat)
498 name = avfc->iformat->name;
499 if (avcc && avcc->codec)
500 codec_name = avcc->codec->name;
503 mtvp->codec_name = codec_name;
505 mtvp->bitrate = avcc->bit_rate;
506 mtvp->width = avcc->width;
507 mtvp->height = avcc->height;
508 mtvp->aspect_num = avcc->sample_aspect_ratio.num;
509 mtvp->aspect_den = avcc->sample_aspect_ratio.den;
512 mtvp->endianness = 0;
515 media_substream_type_properties(mss).vprops = mtvp;
516 media_substream_data(mss) = (void*)st;
519 /* main analysis function */
520 static ms_driver_data_t
521 media_ffmpeg_open(Lisp_Media_Stream *ms)
524 media_substream *mss;
525 /* libavformat stuff */
526 AVFormatContext *avfc = NULL;
527 AVStream *avst = NULL;
528 AVCodecContext *avcc = NULL;
534 switch (media_stream_kind(ms)) {
536 mkind_file_properties *mkfp = NULL;
541 mkfp = media_stream_kind_properties(ms).fprops;
542 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
543 ALLOCA, (file, file_len), Qnil);
544 avfc = media_ffmpeg_open_file(file);
546 media_stream_set_meths(ms, NULL);
547 media_stream_driver(ms) = MDRIVER_UNKNOWN;
551 /* store the filesize */
552 mkfp->filesize = avfc->file_size;
556 mkind_string_properties *mksp = NULL;
561 mksp = media_stream_kind_properties(ms).sprops;
562 data = mksp->stream_data;
564 avfc = media_ffmpeg_open_data(data, size);
567 media_stream_set_meths(ms, NULL);
568 media_stream_driver(ms) = MDRIVER_UNKNOWN;
576 case NUMBER_OF_MEDIA_KINDS:
582 /* check if there is at least one usable stream */
583 for (size_t st = 0; st < avfc->nb_streams; st++) {
584 avst = avfc->streams[st];
587 avcc->codec_id != CODEC_ID_NONE &&
588 avcc->codec_type != AVMEDIA_TYPE_DATA &&
589 (avc = avcodec_find_decoder(avcc->codec_id)) &&
590 (avc && (avcodec_open(avcc, avc) >= 0))) {
592 /* create a substream */
593 mss = make_media_substream_append(ms);
595 switch ((unsigned int)avcc->codec_type) {
596 case AVMEDIA_TYPE_VIDEO:
597 /* assign substream props */
598 media_substream_type(mss) = MTYPE_VIDEO;
599 media_ffmpeg_analyse_video(mss, avfc, st);
601 case AVMEDIA_TYPE_AUDIO:
602 /* assign substream props */
603 media_substream_type(mss) = MTYPE_AUDIO;
604 media_ffmpeg_analyse_audio(mss, avfc, st);
605 /* set some stream handlers */
606 media_stream_set_meths(ms, media_ffmpeg);
608 case AVMEDIA_TYPE_DATA:
609 media_substream_type(mss) = MTYPE_IMAGE;
612 media_substream_type(mss) = MTYPE_UNKNOWN;
618 /* keep the format context */
619 media_stream_data(ms) = avfc;
621 /* set me as driver indicator */
622 media_stream_driver(ms) = MYSELF;
629 handle_packet(AVFormatContext *avfc, AVPacket *pkt)
634 int ret, got_picture;
636 st = avfc->streams[pkt->stream_index];
638 /* XXX: allocate picture correctly */
639 avcodec_get_frame_defaults(&picture);
641 ret = avcodec_decode_video(
642 st->codec, &picture, &got_picture, pkt->data, pkt->size);
650 FFMPEG_DEBUG_AVF("got video frame\n");
660 media_ffmpeg_read(media_substream *mss, void *outbuf, size_t length)
662 /* read at most `length' frames into `outbuf' */
663 /* convert them to internal format */
665 Lisp_Media_Stream *ms = mss->up;
666 mtype_audio_properties *mtap;
667 media_sample_format_t *fmt;
669 AVFormatContext *avfc;
671 AVCodecContext *avcc;
675 /* the size we present here, is _not_ the size we want, however
676 * ffmpeg is quite pedantic about the buffer size,
677 * we just pass the least possible value here to please him */
678 int size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
681 long int bufseek = 0, si = -1;
682 int declen, dec, rf_status = 0;
684 /* check the integrity of the media stream */
685 if (media_stream_driver(ms) != MYSELF)
688 /* fetch the format context */
689 avfc = media_stream_data(ms);
694 si = (long int)mss->substream_data;
695 avst = avfc->streams[si];
699 /* unpack the substream */
700 if ((mtap = media_substream_type_properties(mss).aprops) == NULL) {
701 FFMPEG_DEBUG_AVS("stream information missing. Uh Oh.\n");
705 /* fetch audio info */
706 framesize = mtap->framesize;
709 /* initialise the packet */
710 pkt.pts = pkt.dts = pkt.size = 0;
711 FFMPEG_DEBUG_AVF("initialised packet: "
712 "pts:%lld dts:%lld psz:%d\n",
713 (long long int)pkt.pts,
714 (long long int)pkt.dts,
717 /* read a frame and decode it */
718 while ((size_t)bufseek <= length*framesize &&
719 (rf_status = av_read_frame(avfc, &pkt)) >= 0) {
720 if (pkt.stream_index != si) {
721 FFMPEG_DEBUG_AVF("SKIP reason: "
722 "sought after stream %ld, got %ld\n",
724 (long int)pkt.stream_index);
725 handle_packet(avfc, &pkt);
729 FFMPEG_DEBUG_AVF("read frame: "
730 "pts:%lld dts:%lld psz:%d\n",
731 (long long int)pkt.pts,
732 (long long int)pkt.dts,
736 /* decode the demuxed packet */
737 #ifdef HAVE_AVCODEC_DECODE_AUDIO2
738 /* prefer decode_audio2() if available */
739 size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
740 declen = avcodec_decode_audio2(
741 avcc, (void*)((char*)outbuf+bufseek),
742 &size, pkt.data, pkt.size);
743 #elif defined HAVE_AVCODEC_DECODE_AUDIO
744 declen = avcodec_decode_audio(
745 avcc, (void*)((char*)outbuf+bufseek),
746 &size, pkt.data, pkt.size);
751 if (dec > 0 && size > 0) {
752 FFMPEG_DEBUG_AVF("pts:%lld dts:%lld psz:%d s:%d d:%d\n",
753 (long long int)pkt.pts,
754 (long long int)pkt.dts,
755 pkt.size, size, declen);
757 /* memcpy(outbuf+bufseek, (char*)buffer, size); */
761 FFMPEG_DEBUG_AVF("packet state: "
762 "pts:%lld dts:%lld psz:%d\n",
763 (long long int)pkt.pts,
764 (long long int)pkt.dts,
766 av_free_packet(&pkt);
768 av_free_packet(&pkt);
770 FFMPEG_DEBUG_AVF("finished reading, bufseek=%ld, rf_status=%ld\n",
771 (long int)bufseek, (long int)rf_status);
773 /* convert the pig */
774 size = bufseek/framesize;
775 MEDIA_SAMPLE_FORMAT_UPSAMPLE(fmt)(outbuf, outbuf, size*mtap->channels);
782 media_ffmpeg_rewind(media_substream *mss)
784 /* rewind the stream to the first frame */
786 AVFormatContext *avfc;
788 Lisp_Media_Stream *ms = mss->up;
793 /* check the integrity of the media stream */
794 if (media_stream_driver(ms) != MYSELF)
797 FFMPEG_DEBUG_AVF("rewind substream 0x%lx\n",
798 (long unsigned int)mss);
800 /* fetch the format context */
801 if (!(avfc = media_stream_data(ms)))
804 si = (long int)mss->substream_data;
805 avst = avfc->streams[si];
806 if ((start_time = avst->start_time) < 0) {
810 FFMPEG_DEBUG_AVF("rewind (idx:%ld) to %lld\n",
811 si, (long long int)start_time);
813 /* ... and reset the stream */
814 res = av_seek_frame(avfc, si, AV_NOPTS_VALUE, AVSEEK_FLAG_BACKWARD);
817 FFMPEG_DEBUG_AVF("rewind succeeded\n");
820 FFMPEG_DEBUG_AVF("rewind exitted with %d\n", res);
827 * the size must be big enough to compensate the hardware audio buffersize size
829 #define SAMPLE_ARRAY_SIZE (2*65536)
830 #define VIDEO_PICTURE_QUEUE_SIZE 1
831 #define SUBPICTURE_QUEUE_SIZE 4
832 #define AUDIO_DIFF_AVG_NB 20
833 #define SDL_AUDIO_BUFFER_SIZE 1024
835 #define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
836 #define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
837 #define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
839 #define FF_ALLOC_EVENT 0
840 #define FF_REFRESH_EVENT 1
841 #define FF_QUIT_EVENT 2
843 typedef struct PacketQueue {
844 AVPacketList *first_pkt, *last_pkt;
848 struct sxe_semaphore_s sem;
851 typedef struct VideoPicture {
852 /* presentation time stamp for this picture */
855 int width, height; /* source height & width */
859 typedef struct SubPicture {
860 double pts; /* presentation time stamp for this picture */
864 typedef struct VideoState {
867 AVInputFormat *iformat;
876 int dtg_active_format;
881 double external_clock; /* external clock base */
882 int64_t external_clock_time;
885 double audio_diff_cum; /* used for AV difference average computation */
886 double audio_diff_avg_coef;
887 double audio_diff_threshold;
888 int audio_diff_avg_count;
891 int audio_hw_buf_size;
892 /* samples output by the codec. we reserve more space for avsync
894 uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]
895 /* fixme, this is very gcc centric, what's aligned(x) in icc? */
896 __attribute__((aligned(16)));
897 unsigned int audio_buf_size; /* in bytes */
898 int audio_buf_index; /* in bytes */
900 uint8_t *audio_pkt_data;
903 int show_audio; /* if true, display audio samples */
904 int16_t sample_array[SAMPLE_ARRAY_SIZE];
905 int sample_array_index;
910 int subtitle_stream_changed;
911 AVStream *subtitle_st;
912 PacketQueue subtitleq;
913 SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
914 int subpq_size, subpq_rindex, subpq_windex;
915 struct sxe_semaphore_s subpq_sem;
918 double frame_last_pts;
919 double frame_last_delay;
920 /* pts of last decoded frame / predicted pts of next decoded frame */
925 /* current displayed pts (different from video_clock
926 * if frame fifos are used */
927 double video_current_pts;
928 /* time (av_gettime) at which we updated video_current_pts - used
929 * to have running video pts */
930 int64_t video_current_pts_time;
931 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
932 int pictq_size, pictq_rindex, pictq_windex;
933 struct sxe_semaphore_s pictq_sem;
935 /* QETimer *video_timer; */
939 int width, height, xleft, ytop;
942 /* since we have only one decoding thread, we can use a global
943 variable instead of a thread local variable */
944 static VideoState *global_video_state;
947 /* packet queue handling */
949 packet_queue_init(PacketQueue *q)
951 memset(q, 0, sizeof(PacketQueue));
952 SXE_SEMAPH_INIT(&q->sem);
956 packet_queue_flush(PacketQueue *q)
958 AVPacketList *pkt, *pkt1;
960 SXE_SEMAPH_LOCK(&q->sem);
961 for (pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
963 av_free_packet(&pkt->pkt);
970 SXE_SEMAPH_UNLOCK(&q->sem);
974 packet_queue_end(PacketQueue *q)
976 packet_queue_flush(q);
977 SXE_SEMAPH_FINI(&q->sem);
981 packet_queue_put(PacketQueue *q, AVPacket *pkt)
985 /* duplicate the packet */
986 if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
989 pkt1 = av_malloc(sizeof(AVPacketList));
996 SXE_SEMAPH_LOCK(&q->sem);
1000 q->first_pkt = pkt1;
1002 q->last_pkt->next = pkt1;
1005 q->size += pkt1->pkt.size;
1006 /* XXX: should duplicate packet data in DV case */
1007 SXE_SEMAPH_SIGNAL(&q->sem);
1008 SXE_SEMAPH_UNLOCK(&q->sem);
1013 packet_queue_abort(PacketQueue *q)
1015 SXE_SEMAPH_LOCK(&q->sem);
1017 q->abort_request = 1;
1019 SXE_SEMAPH_SIGNAL(&q->sem);
1020 SXE_SEMAPH_UNLOCK(&q->sem);
1023 /* return < 0 if aborted, 0 if no packet and > 0 if packet. */
1025 packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
1026 __attribute__((unused));
1029 packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
1034 SXE_SEMAPH_LOCK(&q->sem);
1037 if (q->abort_request) {
1042 pkt1 = q->first_pkt;
1044 q->first_pkt = pkt1->next;
1048 q->size -= pkt1->pkt.size;
1053 } else if (!block) {
1057 SXE_SEMAPH_WAIT(&q->sem);
1060 SXE_SEMAPH_UNLOCK(&q->sem);
1064 static uint64_t global_video_pkt_pts = AV_NOPTS_VALUE;
1067 my_get_buffer(struct AVCodecContext *c, AVFrame *pic)
1069 int ret= avcodec_default_get_buffer(c, pic);
1070 uint64_t *pts= av_malloc(sizeof(uint64_t));
1071 *pts= global_video_pkt_pts;
1077 my_release_buffer(struct AVCodecContext *c, AVFrame *pic)
1079 if(pic) av_freep(&pic->opaque);
1080 avcodec_default_release_buffer(c, pic);
1085 stream_component_open(VideoState *is, int stream_index, Lisp_Media_Stream *ms)
1088 media_substream *mss = NULL;
1089 AVFormatContext *ic = is->ic;
1090 AVCodecContext *enc;
1093 if (stream_index < 0 || (size_t)stream_index >= ic->nb_streams) {
1096 enc = ic->streams[stream_index]->codec;
1098 /* prepare audio output */
1099 if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
1101 wanted_spec.freq = enc->sample_rate;
1102 wanted_spec.format = AUDIO_S16SYS;
1104 /* hack for AC3. XXX: suppress that */
1105 if (enc->channels > 2)
1108 wanted_spec.channels = enc->channels;
1109 wanted_spec.silence = 0;
1110 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1111 wanted_spec.callback = sdl_audio_callback;
1112 wanted_spec.userdata = is;
1114 is->audio_hw_buf_size = 0 /* spec.size */;
1117 codec = avcodec_find_decoder(enc->codec_id);
1118 enc->debug_mv = 0 /* debug_mv */;
1119 enc->debug = 0 /* debug */;
1120 enc->workaround_bugs = 0 /* workaround_bugs */;
1121 enc->lowres = 0 /* lowres */;
1123 enc->flags |= CODEC_FLAG_EMU_EDGE;
1124 enc->idct_algo = FF_IDCT_AUTO; /* idct; */
1126 enc->flags2 |= CODEC_FLAG2_FAST;
1127 enc->skip_frame = AVDISCARD_DEFAULT; /* skip_frame; */
1128 enc->skip_idct = AVDISCARD_DEFAULT; /* skip_idct; */
1129 enc->skip_loop_filter = AVDISCARD_DEFAULT; /* skip_loop_filter; */
1131 enc->error_resilience = FF_ER_CAREFUL; /* error_resilience; */
1133 enc->error_concealment = 3; /* error_concealment; */
1135 avcodec_open(enc, codec) < 0)
1137 if (1 /* thread_count */ > 1)
1138 avcodec_thread_init(enc, 1 /*thread_count*/);
1139 enc->thread_count= 1 /* thread_count */;
1141 /* create a substream */
1142 mss = make_media_substream_append(ms);
1144 switch ((unsigned int)enc->codec_type) {
1145 case AVMEDIA_TYPE_AUDIO:
1146 is->audio_stream = stream_index;
1147 is->audio_st = ic->streams[stream_index];
1148 is->audio_buf_size = 0;
1149 is->audio_buf_index = 0;
1151 /* init averaging filter */
1152 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1153 is->audio_diff_avg_count = 0;
1154 /* since we do not have a precise anough audio fifo fullness,
1155 we correct audio sync only if larger than this threshold */
1156 is->audio_diff_threshold =
1157 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1159 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1160 packet_queue_init(&is->audioq);
1162 media_substream_type(mss) = MTYPE_AUDIO;
1163 media_ffmpeg_analyse_audio(mss, is->ic, stream_index);
1165 case AVMEDIA_TYPE_VIDEO:
1166 is->video_stream = stream_index;
1167 is->video_st = ic->streams[stream_index];
1169 is->frame_last_delay = 40e-3;
1171 int64_t tmp = av_gettime();
1172 is->frame_timer = (double)tmp / 1000000.0f;
1174 is->video_current_pts_time = av_gettime();
1176 packet_queue_init(&is->videoq);
1177 is->video_tid = 0 /* SDL_CreateThread(video_thread, is) */;
1179 enc-> get_buffer= my_get_buffer;
1180 enc->release_buffer= my_release_buffer;
1182 media_substream_type(mss) = MTYPE_VIDEO;
1183 media_ffmpeg_analyse_video(mss, is->ic, stream_index);
1185 case AVMEDIA_TYPE_SUBTITLE:
1186 is->subtitle_stream = stream_index;
1187 is->subtitle_st = ic->streams[stream_index];
1188 packet_queue_init(&is->subtitleq);
1190 is->subtitle_tid = 0 /*SDL_CreateThread(subtitle_thread, is)*/;
1199 stream_component_close(VideoState *is, int stream_index)
1201 AVFormatContext *ic = is->ic;
1202 AVCodecContext *enc;
1204 if (stream_index < 0 || (size_t)stream_index >= ic->nb_streams) {
1207 enc = ic->streams[stream_index]->codec;
1209 switch ((unsigned int)enc->codec_type) {
1210 case AVMEDIA_TYPE_AUDIO:
1211 packet_queue_abort(&is->audioq);
1215 packet_queue_end(&is->audioq);
1217 case AVMEDIA_TYPE_VIDEO:
1218 packet_queue_abort(&is->videoq);
1220 /* note: we also signal this mutex to make sure we deblock the
1221 video thread in all cases */
1222 SXE_SEMAPH_LOCK(&is->pictq_sem);
1223 SXE_SEMAPH_SIGNAL(&is->pictq_sem);
1224 SXE_SEMAPH_UNLOCK(&is->pictq_sem);
1226 SDL_WaitThread(is->video_tid, NULL);
1228 packet_queue_end(&is->videoq);
1230 case AVMEDIA_TYPE_SUBTITLE:
1231 packet_queue_abort(&is->subtitleq);
1233 /* note: we also signal this mutex to make sure we deblock the
1234 video thread in all cases */
1235 SXE_SEMAPH_LOCK(&is->subpq_sem);
1236 is->subtitle_stream_changed = 1;
1238 SXE_SEMAPH_SIGNAL(&is->subpq_sem);
1239 SXE_SEMAPH_UNLOCK(&is->subpq_sem);
1241 SDL_WaitThread(is->subtitle_tid, NULL);
1243 packet_queue_end(&is->subtitleq);
1250 switch ((unsigned int)enc->codec_type) {
1251 case AVMEDIA_TYPE_AUDIO:
1252 is->audio_st = NULL;
1253 is->audio_stream = -1;
1255 case AVMEDIA_TYPE_VIDEO:
1256 is->video_st = NULL;
1257 is->video_stream = -1;
1259 case AVMEDIA_TYPE_SUBTITLE:
1260 is->subtitle_st = NULL;
1261 is->subtitle_stream = -1;
1269 dump_stream_info(const AVFormatContext *s)
1271 static const char *keys[] = {
1272 "track", "title", "author", "copyright", "comment",
1273 "album", "date", "genre"
1275 static const size_t nkeys = sizeof(keys)/sizeof(keys[0]);
1277 AVDictionaryEntry *curr = NULL;
1278 if (! s->metadata) {
1279 fprintf(stderr, "No metadata\n");
1283 for (i = 0; i < nkeys; ++i ) {
1284 curr = av_dict_get(s->metadata,
1287 AV_DICT_IGNORE_SUFFIX);
1289 fprintf(stderr, "%s: %s\n", curr->key, curr->value);
1294 AV_SYNC_AUDIO_MASTER, /* default choice */
1295 AV_SYNC_VIDEO_MASTER,
1296 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
1300 stream_open(char *filename, size_t filelen)
1302 VideoState *is = xnew(VideoState);
1303 AVFormatParameters params, *ap = ¶ms;
1306 is->filename = filename;
1307 is->filelen = filelen;
1308 is->iformat = av_find_input_format("fmt");
1312 /* initialise some semaphores */
1313 SXE_SEMAPH_INIT(&is->pictq_sem);
1314 SXE_SEMAPH_INIT(&is->subpq_sem);
1316 is->av_sync_type = AV_SYNC_AUDIO_MASTER;
1317 is->parse_tid = 0; /* SDL_CreateThread(decode_thread, is); */
1319 memset(ap, 0, sizeof(*ap));
1320 /* we force a pause when starting an RTSP stream */
1321 ap->initial_pause = 1;
1323 ap->width = 0; /* frame_width; */
1324 ap->height= 0; /* frame_height; */
1325 ap->time_base= (AVRational){1, 25};
1326 ap->pix_fmt = PIX_FMT_NONE; /* frame_pix_fmt; */
1328 err = av_open_input_file(&is->ic, is->filename, is->iformat, 0, ap);
1329 if (UNLIKELY(err < 0)) {
1330 FFMPEG_DEBUG_AVF("Could not open \"%s\" (errno %d)\n",
1342 /* main analysis function */
1343 static ms_driver_data_t
1344 new_media_ffmpeg_open(Lisp_Media_Stream *ms)
1346 /* the final result */
1347 VideoState *vs = NULL;
1348 int err = 0, use_play = 0;
1349 int wanted_audio_stream = 0;
1350 int wanted_video_stream = 0;
1351 int video_index = -1, audio_index = -1;
1352 mkind_file_properties *mkfp = NULL;
1359 if (media_stream_kind(ms) != MKIND_FILE) {
1364 mkfp = media_stream_kind_properties(ms).fprops;
1365 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
1366 MALLOC, (file, file_len), Qnil);
1367 if (UNLIKELY((vs = stream_open(file, file_len)) == NULL)) {
1368 media_stream_set_meths(ms, NULL);
1369 media_stream_driver(ms) = MDRIVER_UNKNOWN;
1373 #ifdef CONFIG_RTSP_DEMUXER
1374 use_play = (ic->iformat == &rtsp_demuxer);
1379 if (1 /* genpts */) {
1380 vs->ic->flags |= AVFMT_FLAG_GENPTS;
1384 err = av_find_stream_info(vs->ic);
1386 FFMPEG_DEBUG_AVF("\"%s\": "
1387 "could not find codec parameters\n",
1392 * ffplay maybe should not use url_feof() to test for the end */
1393 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
1394 vs->ic->pb->eof_reached = 0;
1395 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
1396 vs->ic->pb.eof_reached = 0;
1400 /* now we can begin to play (RTSP stream only) */
1401 av_read_play(vs->ic);
1404 err = av_find_stream_info(vs->ic);
1406 FFMPEG_DEBUG_AVF("\"%s\": "
1407 "could not find codec parameters\n",
1413 for (size_t i = 0; i < vs->ic->nb_streams; i++) {
1414 AVCodecContext *enc = vs->ic->streams[i]->codec;
1415 switch ((unsigned int)enc->codec_type) {
1416 case AVMEDIA_TYPE_AUDIO:
1417 if ((audio_index < 0 || wanted_audio_stream-- > 0)) {
1421 case AVMEDIA_TYPE_VIDEO:
1422 if ((video_index < 0 || wanted_video_stream-- > 0)) {
1430 if (1 /* show_status */) {
1431 dump_format(vs->ic, 0, vs->filename, 0);
1432 dump_stream_info(vs->ic);
1435 /* open the streams */
1436 if (audio_index >= 0) {
1437 stream_component_open(vs, audio_index, ms);
1440 if (video_index >= 0) {
1441 stream_component_open(vs, video_index, ms);
1446 if (vs->video_stream < 0 && vs->audio_stream < 0) {
1447 FFMPEG_DEBUG_AVF("\"%s\": could not open codecs\n",
1452 /* keep the context */
1453 media_stream_data(ms) = vs;
1454 /* set me as driver indicator */
1455 media_stream_driver(ms) = MYSELF;
1465 new_media_ffmpeg_read(media_substream *mss, void *outbuf, size_t length)
1467 VideoState *is = media_stream_data(mss->up); /* was arg */
1469 AVPacket pkt1, *pkt = &pkt1;
1471 /* stuff normally set on the command line */
1472 int64_t start_time = AV_NOPTS_VALUE;
1474 av_init_packet(&flush_pkt);
1475 FFMPEG_CRITICAL("read\n");
1478 /* if seeking requested, we execute it */
1479 if (start_time != AV_NOPTS_VALUE) {
1482 timestamp = start_time;
1483 /* add the stream start time */
1484 if (ic->start_time != AV_NOPTS_VALUE)
1485 timestamp += ic->start_time;
1486 ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
1488 fprintf(stderr, "%s: could not seek to position %0.3f\n",
1489 is->filename, (double)timestamp / AV_TIME_BASE);
1495 if (is->abort_request) {
1496 FFMPEG_DEBUG_AVF("\n");
1499 if (is->paused != is->last_paused) {
1500 is->last_paused = is->paused;
1502 av_read_pause(is->ic);
1504 av_read_play(is->ic);
1506 #ifdef CONFIG_RTSP_DEMUXER
1507 if (is->paused && is->ic->iformat == &rtsp_demuxer) {
1508 /* wait 10 ms to avoid trying to get another packet */
1515 int stream_index= -1;
1516 int64_t seek_target= is->seek_pos;
1518 if (is->video_stream >= 0)
1519 stream_index = is->video_stream;
1520 else if (is->audio_stream >= 0)
1521 stream_index = is->audio_stream;
1522 else if (is->subtitle_stream >= 0)
1523 stream_index = is->subtitle_stream;
1525 if (stream_index >= 0) {
1526 seek_target = av_rescale_q(
1527 seek_target, AV_TIME_BASE_Q,
1528 is->ic->streams[stream_index]->
1532 ret = av_seek_frame(is->ic, stream_index,
1533 seek_target, is->seek_flags);
1535 FFMPEG_DEBUG_AVS("\"%s: \""
1536 "error while seeking\n",
1539 if (is->audio_stream >= 0) {
1540 packet_queue_flush(&is->audioq);
1541 packet_queue_put(&is->audioq, &flush_pkt);
1543 if (is->subtitle_stream >= 0) {
1544 packet_queue_flush(&is->subtitleq);
1545 packet_queue_put(&is->subtitleq, &flush_pkt);
1547 if (is->video_stream >= 0) {
1548 packet_queue_flush(&is->videoq);
1549 packet_queue_put(&is->videoq, &flush_pkt);
1555 /* if the queue are full, no need to read more */
1556 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
1557 is->videoq.size > MAX_VIDEOQ_SIZE ||
1558 is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
1559 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
1560 url_feof(is->ic->pb)
1561 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
1562 url_feof(&is->ic->pb)
1569 ret = av_read_frame(is->ic, pkt);
1572 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
1574 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
1578 usleep(100); /* wait for user event */
1583 if (pkt->stream_index == is->audio_stream) {
1584 packet_queue_put(&is->audioq, pkt);
1585 } else if (pkt->stream_index == is->video_stream) {
1586 packet_queue_put(&is->videoq, pkt);
1587 } else if (pkt->stream_index == is->subtitle_stream) {
1588 packet_queue_put(&is->subtitleq, pkt);
1590 av_free_packet(pkt);
1593 /* wait until the end */
1594 while (!is->abort_request) {
1599 /* disable interrupting */
1600 global_video_state = NULL;
1602 /* close each stream */
1603 if (is->audio_stream >= 0)
1604 stream_component_close(is, is->audio_stream);
1605 if (is->video_stream >= 0)
1606 stream_component_close(is, is->video_stream);
1607 if (is->subtitle_stream >= 0)
1608 stream_component_close(is, is->subtitle_stream);
1610 av_close_input_file(is->ic);
1611 is->ic = NULL; /* safety */
1613 url_set_interrupt_cb(NULL);
1619 event.type = FF_QUIT_EVENT;
1620 event.user.data1 = is;
1621 SDL_PushEvent(&event);
1628 new_media_ffmpeg_rewind(media_substream *mss)
1630 /* rewind the stream to the first frame */
1632 AVFormatContext *avfc;
1634 Lisp_Media_Stream *ms = mss->up;
1639 /* check the integrity of the media stream */
1640 if (media_stream_driver(ms) != MYSELF)
1643 FFMPEG_DEBUG_AVF("rewind substream 0x%lx\n",
1644 (long unsigned int)mss);
1646 /* fetch the format context */
1647 if (!(avfc = media_stream_data(ms)))
1650 si = (long int)mss->substream_data;
1651 avst = avfc->streams[si];
1652 if ((start_time = avst->start_time) < 0) {
1656 FFMPEG_DEBUG_AVF("rewind (idx:%ld) to %lld\n",
1657 si, (long long int)start_time);
1659 /* ... and reset the stream */
1660 res = av_seek_frame(avfc, -1, start_time, AVSEEK_FLAG_BACKWARD);
1663 FFMPEG_DEBUG_AVF("rewind succeeded\n");
1666 FFMPEG_DEBUG_AVF("rewind exitted with %d\n", res);
1673 media_ffmpeg_available_formats(void)
1675 Lisp_Object formats;
1676 AVInputFormat *avif;
1681 avif = first_iformat;
1685 const Lisp_Object fmtname =
1686 Fintern(build_string(avif->name), Qnil);
1687 formats = Fcons(fmtname, formats);