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;
133 int chars_left = 4095;
135 avfc = media_stream_data(ms);
136 out = xmalloc_atomic(chars_left+1);
138 out[chars_left] = '\0';
140 /* cannot use ffmpeg on corrupt streams */
141 if (media_stream_driver(ms) != MYSELF || avfc == NULL)
144 if (avfc->author && *avfc->author) {
145 strncat(out, " :author \"", chars_left);
147 strncat(out, avfc->author, chars_left);
148 chars_left -= strlen(avfc->author);
149 strncat(out, "\"", chars_left--);
151 if (avfc->title && *avfc->title) {
152 strncat(out, " :title: \"", chars_left);
154 strncat(out, avfc->title, chars_left);
155 chars_left -= strlen(avfc->title);
156 strncat(out, "\"", chars_left--);
160 int sz = snprintf(year, sizeof(year), "%d", avfc->year);
161 assert(sz>=0 && sz<sizeof(year));
162 strncat(out, " :year ", chars_left);
164 strncat(out, year, chars_left);
171 media_ffmpeg_print(Lisp_Object ms, Lisp_Object pcfun, int ef)
176 static AVFormatContext*
177 media_ffmpeg_open_file(const char *file)
179 #if defined HAVE_AVFORMAT_ALLOC_CONTEXT
180 AVFormatContext *avfc = avformat_alloc_context();
181 #elif defined HAVE_AV_ALLOC_FORMAT_CONTEXT
182 /* deprecated already, but `people' like Horst still use this */
183 AVFormatContext *avfc = av_alloc_format_context();
185 # error "Your ffmpeg library is too old. Adopt a new one."
186 #endif /* HAVE_AVFORMAT_ALLOC_CONTEXT */
189 if (av_open_input_file(&avfc, file, NULL, 0, NULL) < 0) {
190 FFMPEG_DEBUG_AVF("opening file failed.\n");
196 /* Retrieve stream information */
197 if (av_find_stream_info(avfc) < 0) {
198 FFMPEG_DEBUG_AVS("opening stream inside file failed.\n");
199 av_close_input_file(avfc);
210 media_ffmpeg_vio_open(URLContext *h, const char *filename, int flags)
216 media_ffmpeg_vio_read(URLContext *h, unsigned char *buf, int size)
218 media_data *sd = (media_data*)h->priv_data;
220 FFMPEG_DEBUG_AVS("reading %d bytes to 0x%x, respecting seek %ld\n",
221 size, (unsigned int)buf, sd->seek);
223 if ((long int)sd->length <= sd->seek) {
224 FFMPEG_DEBUG_AVS("eof\n");
228 memcpy(buf, sd->data+sd->seek, size);
235 media_ffmpeg_vio_write(URLContext *h, unsigned char *buf, int size)
241 media_ffmpeg_vio_seek(URLContext *h, int64_t pos, int whence)
243 media_data *sd = (media_data*)h->priv_data;
245 FFMPEG_DEBUG_AVS("seeking to %ld via %d\n", (long int)pos, whence);
252 sd->seek = sd->seek+pos;
255 sd->seek = sd->length+pos;
265 media_ffmpeg_vio_close(URLContext *h)
273 /* this is a memory-i/o protocol in case we have to deal with string data */
274 static URLProtocol media_ffmpeg_protocol = {
276 media_ffmpeg_vio_open,
277 media_ffmpeg_vio_read,
278 media_ffmpeg_vio_write,
279 media_ffmpeg_vio_seek,
280 media_ffmpeg_vio_close,
283 /** Size of probe buffer, for guessing file type from file contents. */
284 #define PROBE_BUF_MIN 2048
285 #define PROBE_BUF_MAX 131072
288 media_ffmpeg_open_data(char *data, size_t size)
290 #if defined HAVE_AVFORMAT_ALLOC_CONTEXT
291 AVFormatContext *avfc = avformat_alloc_context();
292 #elif defined HAVE_AV_ALLOC_FORMAT_CONTEXT
293 /* deprecated already, but `people' like Horst still use this */
294 AVFormatContext *avfc = av_alloc_format_context();
296 # error "Your ffmpeg library is too old. Adopt a new one."
297 #endif /* HAVE_AVFORMAT_ALLOC_CONTEXT */
298 AVProbeData *pd = NULL;
299 ByteIOContext *bioctx = NULL;
300 AVInputFormat *fmt = NULL;
301 char file[] = "SXEmff:SXEmacs.mp3\000";
302 media_data *sd = NULL;
304 /* register our virtual i/o */
305 #if defined HAVE_AV_REGISTER_PROTOCOL
306 av_register_protocol(&media_ffmpeg_protocol);
307 #elif defined HAVE_REGISTER_PROTOCOL
308 register_protocol(&media_ffmpeg_protocol);
310 # error "Get a recent ffmpeg or get a life."
313 /* initialise our media_data */
314 sd = xnew_and_zero(media_data);
319 /* register ffmpeg byteio */
320 bioctx = xnew_and_zero(ByteIOContext);
321 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
322 url_fopen(&bioctx, file, URL_RDONLY);
323 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
324 url_fopen(bioctx, file, URL_RDONLY);
326 /* erm, register us at the byteio context */
327 ((URLContext*)(bioctx->opaque))->priv_data = sd;
330 pd = xnew_and_zero(AVProbeData);
335 pd->buf = (void*)sd->data;
336 pd->buf_size = PROBE_BUF_MIN;
337 fmt = av_probe_input_format(pd, 1);
339 /* if still no format found, error */
349 if (av_open_input_stream(&avfc, bioctx, file, fmt, NULL) < 0) {
357 /* Retrieve stream information */
358 if (av_find_stream_info(avfc) < 0) {
370 media_ffmpeg_close(ms_driver_data_t data)
372 AVFormatContext *avfc = (AVFormatContext*)data;
373 FFMPEG_DEBUG_AVF("closing AVFormatContext: 0x%lx\n",
374 (long unsigned int)avfc);
375 if (avfc && avfc->iformat)
376 av_close_input_file(avfc);
380 media_ffmpeg_analyse_audio(media_substream *mss, AVFormatContext *avfc, int st)
382 mtype_audio_properties *mtap;
383 const char *name = NULL;
384 const char *codec_name = NULL;
385 /* libavformat cruft */
386 AVStream *avst = NULL;
387 AVCodecContext *avcc = NULL;
389 /* unpack the stream and codec context from the container, again */
391 avst = avfc->streams[st];
396 mtap = xnew_and_zero(mtype_audio_properties);
399 if (avfc && avfc->iformat)
400 name = avfc->iformat->name;
401 if (avcc && avcc->codec)
402 codec_name = avcc->codec->name;
405 mtap->codec_name = codec_name;
407 mtap->channels = avcc->channels;
408 mtap->samplerate = avcc->sample_rate;
409 mtap->bitrate = media_ffmpeg_bitrate(avcc);
411 /* samplewidth and framesize */
412 switch (avcc->sample_fmt) {
414 mtap->samplewidth = 8;
415 mtap->framesize = mtap->channels * 1;
416 mtap->msf = sxe_msf_U8;
419 mtap->samplewidth = 16;
420 mtap->framesize = mtap->channels * 2;
421 mtap->msf = sxe_msf_S16;
423 #if defined SAMPLE_FMT_S24
425 mtap->samplewidth = 32;
426 mtap->framesize = mtap->channels * 4;
427 mtap->msf = sxe_msf_S24;
429 #endif /* SAMPLE_FMT_S24 */
431 mtap->samplewidth = 32;
432 mtap->framesize = mtap->channels * 4;
433 mtap->msf = sxe_msf_S32;
436 mtap->samplewidth = 8*sizeof(float);
437 mtap->framesize = mtap->channels * sizeof(float);
438 mtap->msf = sxe_msf_FLT;
440 case SAMPLE_FMT_NONE:
442 mtap->samplewidth = 0;
446 mtap->endianness = 0;
449 media_substream_type_properties(mss).aprops = mtap;
450 media_substream_data(mss) = (void*)st;
454 media_ffmpeg_analyse_video(media_substream *mss, AVFormatContext *avfc, int st)
456 mtype_video_properties *mtvp;
457 const char *name = NULL;
458 const char *codec_name = NULL;
459 /* libavformat cruft */
460 AVStream *avst = NULL;
461 AVCodecContext *avcc = NULL;
463 /* unpack the stream and codec context from the container, again */
465 avst = avfc->streams[st];
470 mtvp = xnew_and_zero(mtype_video_properties);
473 if (avfc && avfc->iformat)
474 name = avfc->iformat->name;
475 if (avcc && avcc->codec)
476 codec_name = avcc->codec->name;
479 mtvp->codec_name = codec_name;
481 mtvp->bitrate = avcc->bit_rate;
482 mtvp->width = avcc->width;
483 mtvp->height = avcc->height;
484 mtvp->aspect_num = avcc->sample_aspect_ratio.num;
485 mtvp->aspect_den = avcc->sample_aspect_ratio.den;
488 mtvp->endianness = 0;
491 media_substream_type_properties(mss).vprops = mtvp;
492 media_substream_data(mss) = (void*)st;
495 /* main analysis function */
496 static ms_driver_data_t
497 media_ffmpeg_open(Lisp_Media_Stream *ms)
500 media_substream *mss;
501 /* libavformat stuff */
502 AVFormatContext *avfc = NULL;
503 AVStream *avst = NULL;
504 AVCodecContext *avcc = NULL;
510 switch (media_stream_kind(ms)) {
512 mkind_file_properties *mkfp = NULL;
517 mkfp = media_stream_kind_properties(ms).fprops;
518 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
519 ALLOCA, (file, file_len), Qnil);
520 avfc = media_ffmpeg_open_file(file);
522 media_stream_set_meths(ms, NULL);
523 media_stream_driver(ms) = MDRIVER_UNKNOWN;
527 /* store the filesize */
528 mkfp->filesize = avfc->file_size;
532 mkind_string_properties *mksp = NULL;
537 mksp = media_stream_kind_properties(ms).sprops;
538 data = mksp->stream_data;
540 avfc = media_ffmpeg_open_data(data, size);
543 media_stream_set_meths(ms, NULL);
544 media_stream_driver(ms) = MDRIVER_UNKNOWN;
552 case NUMBER_OF_MEDIA_KINDS:
558 /* check if there is at least one usable stream */
559 for (size_t st = 0; st < avfc->nb_streams; st++) {
560 avst = avfc->streams[st];
563 avcc->codec_id != CODEC_ID_NONE &&
564 avcc->codec_type != CODEC_TYPE_DATA &&
565 (avc = avcodec_find_decoder(avcc->codec_id)) &&
566 (avc && (avcodec_open(avcc, avc) >= 0))) {
568 /* create a substream */
569 mss = make_media_substream_append(ms);
571 switch ((unsigned int)avcc->codec_type) {
572 case CODEC_TYPE_VIDEO:
573 /* assign substream props */
574 media_substream_type(mss) = MTYPE_VIDEO;
575 media_ffmpeg_analyse_video(mss, avfc, st);
577 case CODEC_TYPE_AUDIO:
578 /* assign substream props */
579 media_substream_type(mss) = MTYPE_AUDIO;
580 media_ffmpeg_analyse_audio(mss, avfc, st);
581 /* set some stream handlers */
582 media_stream_set_meths(ms, media_ffmpeg);
584 case CODEC_TYPE_DATA:
585 media_substream_type(mss) = MTYPE_IMAGE;
588 media_substream_type(mss) = MTYPE_UNKNOWN;
594 /* keep the format context */
595 media_stream_data(ms) = avfc;
597 /* set me as driver indicator */
598 media_stream_driver(ms) = MYSELF;
605 handle_packet(AVFormatContext *avfc, AVPacket *pkt)
610 int ret, got_picture;
612 st = avfc->streams[pkt->stream_index];
614 /* XXX: allocate picture correctly */
615 avcodec_get_frame_defaults(&picture);
617 ret = avcodec_decode_video(
618 st->codec, &picture, &got_picture, pkt->data, pkt->size);
626 FFMPEG_DEBUG_AVF("got video frame\n");
636 media_ffmpeg_read(media_substream *mss, void *outbuf, size_t length)
638 /* read at most `length' frames into `outbuf' */
639 /* convert them to internal format */
641 Lisp_Media_Stream *ms = mss->up;
642 mtype_audio_properties *mtap;
643 media_sample_format_t *fmt;
645 AVFormatContext *avfc;
647 AVCodecContext *avcc;
651 /* the size we present here, is _not_ the size we want, however
652 * ffmpeg is quite pedantic about the buffer size,
653 * we just pass the least possible value here to please him */
654 int size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
657 long int bufseek = 0, si = -1;
658 int declen, dec, rf_status = 0;
660 /* check the integrity of the media stream */
661 if (media_stream_driver(ms) != MYSELF)
664 /* fetch the format context */
665 avfc = media_stream_data(ms);
670 si = (long int)mss->substream_data;
671 avst = avfc->streams[si];
675 /* unpack the substream */
676 if ((mtap = media_substream_type_properties(mss).aprops) == NULL) {
677 FFMPEG_DEBUG_AVS("stream information missing. Uh Oh.\n");
681 /* fetch audio info */
682 framesize = mtap->framesize;
685 /* initialise the packet */
686 pkt.pts = pkt.dts = pkt.size = 0;
687 FFMPEG_DEBUG_AVF("initialised packet: "
688 "pts:%lld dts:%lld psz:%d\n",
689 (long long int)pkt.pts,
690 (long long int)pkt.dts,
693 /* read a frame and decode it */
694 while ((size_t)bufseek <= length*framesize &&
695 (rf_status = av_read_frame(avfc, &pkt)) >= 0) {
696 if (pkt.stream_index != si) {
697 FFMPEG_DEBUG_AVF("SKIP reason: "
698 "sought after stream %ld, got %ld\n",
700 (long int)pkt.stream_index);
701 handle_packet(avfc, &pkt);
705 FFMPEG_DEBUG_AVF("read frame: "
706 "pts:%lld dts:%lld psz:%d\n",
707 (long long int)pkt.pts,
708 (long long int)pkt.dts,
712 /* decode the demuxed packet */
713 #ifdef HAVE_AVCODEC_DECODE_AUDIO2
714 /* prefer decode_audio2() if available */
715 size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
716 declen = avcodec_decode_audio2(
717 avcc, (void*)((char*)outbuf+bufseek),
718 &size, pkt.data, pkt.size);
719 #elif defined HAVE_AVCODEC_DECODE_AUDIO
720 declen = avcodec_decode_audio(
721 avcc, (void*)((char*)outbuf+bufseek),
722 &size, pkt.data, pkt.size);
727 if (dec > 0 && size > 0) {
728 FFMPEG_DEBUG_AVF("pts:%lld dts:%lld psz:%d s:%d d:%d\n",
729 (long long int)pkt.pts,
730 (long long int)pkt.dts,
731 pkt.size, size, declen);
733 /* memcpy(outbuf+bufseek, (char*)buffer, size); */
737 FFMPEG_DEBUG_AVF("packet state: "
738 "pts:%lld dts:%lld psz:%d\n",
739 (long long int)pkt.pts,
740 (long long int)pkt.dts,
742 av_free_packet(&pkt);
744 av_free_packet(&pkt);
746 FFMPEG_DEBUG_AVF("finished reading, bufseek=%ld, rf_status=%ld\n",
747 (long int)bufseek, (long int)rf_status);
749 /* convert the pig */
750 size = bufseek/framesize;
751 MEDIA_SAMPLE_FORMAT_UPSAMPLE(fmt)(outbuf, outbuf, size*mtap->channels);
758 media_ffmpeg_rewind(media_substream *mss)
760 /* rewind the stream to the first frame */
762 AVFormatContext *avfc;
764 Lisp_Media_Stream *ms = mss->up;
769 /* check the integrity of the media stream */
770 if (media_stream_driver(ms) != MYSELF)
773 FFMPEG_DEBUG_AVF("rewind substream 0x%lx\n",
774 (long unsigned int)mss);
776 /* fetch the format context */
777 if (!(avfc = media_stream_data(ms)))
780 si = (long int)mss->substream_data;
781 avst = avfc->streams[si];
782 if ((start_time = avst->start_time) < 0) {
786 FFMPEG_DEBUG_AVF("rewind (idx:%ld) to %lld\n",
787 si, (long long int)start_time);
789 /* ... and reset the stream */
790 res = av_seek_frame(avfc, si, AV_NOPTS_VALUE, AVSEEK_FLAG_BACKWARD);
793 FFMPEG_DEBUG_AVF("rewind succeeded\n");
796 FFMPEG_DEBUG_AVF("rewind exitted with %d\n", res);
803 * the size must be big enough to compensate the hardware audio buffersize size
805 #define SAMPLE_ARRAY_SIZE (2*65536)
806 #define VIDEO_PICTURE_QUEUE_SIZE 1
807 #define SUBPICTURE_QUEUE_SIZE 4
808 #define AUDIO_DIFF_AVG_NB 20
809 #define SDL_AUDIO_BUFFER_SIZE 1024
811 #define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
812 #define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
813 #define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
815 #define FF_ALLOC_EVENT 0
816 #define FF_REFRESH_EVENT 1
817 #define FF_QUIT_EVENT 2
819 typedef struct PacketQueue {
820 AVPacketList *first_pkt, *last_pkt;
824 struct sxe_semaphore_s sem;
827 typedef struct VideoPicture {
828 /* presentation time stamp for this picture */
831 int width, height; /* source height & width */
835 typedef struct SubPicture {
836 double pts; /* presentation time stamp for this picture */
840 typedef struct VideoState {
843 AVInputFormat *iformat;
852 int dtg_active_format;
857 double external_clock; /* external clock base */
858 int64_t external_clock_time;
861 double audio_diff_cum; /* used for AV difference average computation */
862 double audio_diff_avg_coef;
863 double audio_diff_threshold;
864 int audio_diff_avg_count;
867 int audio_hw_buf_size;
868 /* samples output by the codec. we reserve more space for avsync
870 uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]
871 /* fixme, this is very gcc centric, what's aligned(x) in icc? */
872 __attribute__((aligned(16)));
873 unsigned int audio_buf_size; /* in bytes */
874 int audio_buf_index; /* in bytes */
876 uint8_t *audio_pkt_data;
879 int show_audio; /* if true, display audio samples */
880 int16_t sample_array[SAMPLE_ARRAY_SIZE];
881 int sample_array_index;
886 int subtitle_stream_changed;
887 AVStream *subtitle_st;
888 PacketQueue subtitleq;
889 SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
890 int subpq_size, subpq_rindex, subpq_windex;
891 struct sxe_semaphore_s subpq_sem;
894 double frame_last_pts;
895 double frame_last_delay;
896 /* pts of last decoded frame / predicted pts of next decoded frame */
901 /* current displayed pts (different from video_clock
902 * if frame fifos are used */
903 double video_current_pts;
904 /* time (av_gettime) at which we updated video_current_pts - used
905 * to have running video pts */
906 int64_t video_current_pts_time;
907 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
908 int pictq_size, pictq_rindex, pictq_windex;
909 struct sxe_semaphore_s pictq_sem;
911 /* QETimer *video_timer; */
915 int width, height, xleft, ytop;
918 /* since we have only one decoding thread, we can use a global
919 variable instead of a thread local variable */
920 static VideoState *global_video_state;
923 /* packet queue handling */
925 packet_queue_init(PacketQueue *q)
927 memset(q, 0, sizeof(PacketQueue));
928 SXE_SEMAPH_INIT(&q->sem);
932 packet_queue_flush(PacketQueue *q)
934 AVPacketList *pkt, *pkt1;
936 SXE_SEMAPH_LOCK(&q->sem);
937 for (pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
939 av_free_packet(&pkt->pkt);
946 SXE_SEMAPH_UNLOCK(&q->sem);
950 packet_queue_end(PacketQueue *q)
952 packet_queue_flush(q);
953 SXE_SEMAPH_FINI(&q->sem);
957 packet_queue_put(PacketQueue *q, AVPacket *pkt)
961 /* duplicate the packet */
962 if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
965 pkt1 = av_malloc(sizeof(AVPacketList));
972 SXE_SEMAPH_LOCK(&q->sem);
978 q->last_pkt->next = pkt1;
981 q->size += pkt1->pkt.size;
982 /* XXX: should duplicate packet data in DV case */
983 SXE_SEMAPH_SIGNAL(&q->sem);
984 SXE_SEMAPH_UNLOCK(&q->sem);
989 packet_queue_abort(PacketQueue *q)
991 SXE_SEMAPH_LOCK(&q->sem);
993 q->abort_request = 1;
995 SXE_SEMAPH_SIGNAL(&q->sem);
996 SXE_SEMAPH_UNLOCK(&q->sem);
999 /* return < 0 if aborted, 0 if no packet and > 0 if packet. */
1001 packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
1002 __attribute__((unused));
1005 packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
1010 SXE_SEMAPH_LOCK(&q->sem);
1013 if (q->abort_request) {
1018 pkt1 = q->first_pkt;
1020 q->first_pkt = pkt1->next;
1024 q->size -= pkt1->pkt.size;
1029 } else if (!block) {
1033 SXE_SEMAPH_WAIT(&q->sem);
1036 SXE_SEMAPH_UNLOCK(&q->sem);
1040 static uint64_t global_video_pkt_pts = AV_NOPTS_VALUE;
1043 my_get_buffer(struct AVCodecContext *c, AVFrame *pic)
1045 int ret= avcodec_default_get_buffer(c, pic);
1046 uint64_t *pts= av_malloc(sizeof(uint64_t));
1047 *pts= global_video_pkt_pts;
1053 my_release_buffer(struct AVCodecContext *c, AVFrame *pic)
1055 if(pic) av_freep(&pic->opaque);
1056 avcodec_default_release_buffer(c, pic);
1061 stream_component_open(VideoState *is, int stream_index, Lisp_Media_Stream *ms)
1064 media_substream *mss = NULL;
1065 AVFormatContext *ic = is->ic;
1066 AVCodecContext *enc;
1069 if (stream_index < 0 || (size_t)stream_index >= ic->nb_streams) {
1072 enc = ic->streams[stream_index]->codec;
1074 /* prepare audio output */
1075 if (enc->codec_type == CODEC_TYPE_AUDIO) {
1077 wanted_spec.freq = enc->sample_rate;
1078 wanted_spec.format = AUDIO_S16SYS;
1080 /* hack for AC3. XXX: suppress that */
1081 if (enc->channels > 2)
1084 wanted_spec.channels = enc->channels;
1085 wanted_spec.silence = 0;
1086 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1087 wanted_spec.callback = sdl_audio_callback;
1088 wanted_spec.userdata = is;
1090 is->audio_hw_buf_size = 0 /* spec.size */;
1093 codec = avcodec_find_decoder(enc->codec_id);
1094 enc->debug_mv = 0 /* debug_mv */;
1095 enc->debug = 0 /* debug */;
1096 enc->workaround_bugs = 0 /* workaround_bugs */;
1097 enc->lowres = 0 /* lowres */;
1099 enc->flags |= CODEC_FLAG_EMU_EDGE;
1100 enc->idct_algo = FF_IDCT_AUTO; /* idct; */
1102 enc->flags2 |= CODEC_FLAG2_FAST;
1103 enc->skip_frame = AVDISCARD_DEFAULT; /* skip_frame; */
1104 enc->skip_idct = AVDISCARD_DEFAULT; /* skip_idct; */
1105 enc->skip_loop_filter = AVDISCARD_DEFAULT; /* skip_loop_filter; */
1107 enc->error_resilience = FF_ER_CAREFUL; /* error_resilience; */
1109 enc->error_concealment = 3; /* error_concealment; */
1111 avcodec_open(enc, codec) < 0)
1113 if (1 /* thread_count */ > 1)
1114 avcodec_thread_init(enc, 1 /*thread_count*/);
1115 enc->thread_count= 1 /* thread_count */;
1117 /* create a substream */
1118 mss = make_media_substream_append(ms);
1120 switch ((unsigned int)enc->codec_type) {
1121 case CODEC_TYPE_AUDIO:
1122 is->audio_stream = stream_index;
1123 is->audio_st = ic->streams[stream_index];
1124 is->audio_buf_size = 0;
1125 is->audio_buf_index = 0;
1127 /* init averaging filter */
1128 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1129 is->audio_diff_avg_count = 0;
1130 /* since we do not have a precise anough audio fifo fullness,
1131 we correct audio sync only if larger than this threshold */
1132 is->audio_diff_threshold =
1133 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1135 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1136 packet_queue_init(&is->audioq);
1138 media_substream_type(mss) = MTYPE_AUDIO;
1139 media_ffmpeg_analyse_audio(mss, is->ic, stream_index);
1141 case CODEC_TYPE_VIDEO:
1142 is->video_stream = stream_index;
1143 is->video_st = ic->streams[stream_index];
1145 is->frame_last_delay = 40e-3;
1147 int64_t tmp = av_gettime();
1148 is->frame_timer = (double)tmp / 1000000.0f;
1150 is->video_current_pts_time = av_gettime();
1152 packet_queue_init(&is->videoq);
1153 is->video_tid = 0 /* SDL_CreateThread(video_thread, is) */;
1155 enc-> get_buffer= my_get_buffer;
1156 enc->release_buffer= my_release_buffer;
1158 media_substream_type(mss) = MTYPE_VIDEO;
1159 media_ffmpeg_analyse_video(mss, is->ic, stream_index);
1161 case CODEC_TYPE_SUBTITLE:
1162 is->subtitle_stream = stream_index;
1163 is->subtitle_st = ic->streams[stream_index];
1164 packet_queue_init(&is->subtitleq);
1166 is->subtitle_tid = 0 /*SDL_CreateThread(subtitle_thread, is)*/;
1175 stream_component_close(VideoState *is, int stream_index)
1177 AVFormatContext *ic = is->ic;
1178 AVCodecContext *enc;
1180 if (stream_index < 0 || (size_t)stream_index >= ic->nb_streams) {
1183 enc = ic->streams[stream_index]->codec;
1185 switch ((unsigned int)enc->codec_type) {
1186 case CODEC_TYPE_AUDIO:
1187 packet_queue_abort(&is->audioq);
1191 packet_queue_end(&is->audioq);
1193 case CODEC_TYPE_VIDEO:
1194 packet_queue_abort(&is->videoq);
1196 /* note: we also signal this mutex to make sure we deblock the
1197 video thread in all cases */
1198 SXE_SEMAPH_LOCK(&is->pictq_sem);
1199 SXE_SEMAPH_SIGNAL(&is->pictq_sem);
1200 SXE_SEMAPH_UNLOCK(&is->pictq_sem);
1202 SDL_WaitThread(is->video_tid, NULL);
1204 packet_queue_end(&is->videoq);
1206 case CODEC_TYPE_SUBTITLE:
1207 packet_queue_abort(&is->subtitleq);
1209 /* note: we also signal this mutex to make sure we deblock the
1210 video thread in all cases */
1211 SXE_SEMAPH_LOCK(&is->subpq_sem);
1212 is->subtitle_stream_changed = 1;
1214 SXE_SEMAPH_SIGNAL(&is->subpq_sem);
1215 SXE_SEMAPH_UNLOCK(&is->subpq_sem);
1217 SDL_WaitThread(is->subtitle_tid, NULL);
1219 packet_queue_end(&is->subtitleq);
1226 switch ((unsigned int)enc->codec_type) {
1227 case CODEC_TYPE_AUDIO:
1228 is->audio_st = NULL;
1229 is->audio_stream = -1;
1231 case CODEC_TYPE_VIDEO:
1232 is->video_st = NULL;
1233 is->video_stream = -1;
1235 case CODEC_TYPE_SUBTITLE:
1236 is->subtitle_st = NULL;
1237 is->subtitle_stream = -1;
1245 dump_stream_info(const AVFormatContext *s)
1248 fprintf(stderr, "Track: %d\n", s->track);
1249 if (s->title[0] != '\0')
1250 fprintf(stderr, "Title: %s\n", s->title);
1251 if (s->author[0] != '\0')
1252 fprintf(stderr, "Author: %s\n", s->author);
1253 if (s->copyright[0] != '\0')
1254 fprintf(stderr, "Copyright: %s\n", s->copyright);
1255 if (s->comment[0] != '\0')
1256 fprintf(stderr, "Comment: %s\n", s->comment);
1257 if (s->album[0] != '\0')
1258 fprintf(stderr, "Album: %s\n", s->album);
1260 fprintf(stderr, "Year: %d\n", s->year);
1261 if (s->genre[0] != '\0')
1262 fprintf(stderr, "Genre: %s\n", s->genre);
1266 AV_SYNC_AUDIO_MASTER, /* default choice */
1267 AV_SYNC_VIDEO_MASTER,
1268 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
1272 stream_open(char *filename, size_t filelen)
1274 VideoState *is = xnew(VideoState);
1275 AVFormatParameters params, *ap = ¶ms;
1278 is->filename = filename;
1279 is->filelen = filelen;
1280 is->iformat = av_find_input_format("fmt");
1284 /* initialise some semaphores */
1285 SXE_SEMAPH_INIT(&is->pictq_sem);
1286 SXE_SEMAPH_INIT(&is->subpq_sem);
1288 is->av_sync_type = AV_SYNC_AUDIO_MASTER;
1289 is->parse_tid = 0; /* SDL_CreateThread(decode_thread, is); */
1291 memset(ap, 0, sizeof(*ap));
1292 /* we force a pause when starting an RTSP stream */
1293 ap->initial_pause = 1;
1295 ap->width = 0; /* frame_width; */
1296 ap->height= 0; /* frame_height; */
1297 ap->time_base= (AVRational){1, 25};
1298 ap->pix_fmt = PIX_FMT_NONE; /* frame_pix_fmt; */
1300 err = av_open_input_file(&is->ic, is->filename, is->iformat, 0, ap);
1301 if (UNLIKELY(err < 0)) {
1302 FFMPEG_DEBUG_AVF("Could not open \"%s\" (errno %d)\n",
1314 /* main analysis function */
1315 static ms_driver_data_t
1316 new_media_ffmpeg_open(Lisp_Media_Stream *ms)
1318 /* the final result */
1319 VideoState *vs = NULL;
1320 int err = 0, use_play = 0;
1321 int wanted_audio_stream = 0;
1322 int wanted_video_stream = 0;
1323 int video_index = -1, audio_index = -1;
1324 mkind_file_properties *mkfp = NULL;
1331 if (media_stream_kind(ms) != MKIND_FILE) {
1336 mkfp = media_stream_kind_properties(ms).fprops;
1337 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
1338 MALLOC, (file, file_len), Qnil);
1339 if (UNLIKELY((vs = stream_open(file, file_len)) == NULL)) {
1340 media_stream_set_meths(ms, NULL);
1341 media_stream_driver(ms) = MDRIVER_UNKNOWN;
1345 #ifdef CONFIG_RTSP_DEMUXER
1346 use_play = (ic->iformat == &rtsp_demuxer);
1351 if (1 /* genpts */) {
1352 vs->ic->flags |= AVFMT_FLAG_GENPTS;
1356 err = av_find_stream_info(vs->ic);
1358 FFMPEG_DEBUG_AVF("\"%s\": "
1359 "could not find codec parameters\n",
1364 * ffplay maybe should not use url_feof() to test for the end */
1365 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
1366 vs->ic->pb->eof_reached = 0;
1367 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
1368 vs->ic->pb.eof_reached = 0;
1372 /* now we can begin to play (RTSP stream only) */
1373 av_read_play(vs->ic);
1376 err = av_find_stream_info(vs->ic);
1378 FFMPEG_DEBUG_AVF("\"%s\": "
1379 "could not find codec parameters\n",
1385 for (size_t i = 0; i < vs->ic->nb_streams; i++) {
1386 AVCodecContext *enc = vs->ic->streams[i]->codec;
1387 switch ((unsigned int)enc->codec_type) {
1388 case CODEC_TYPE_AUDIO:
1389 if ((audio_index < 0 || wanted_audio_stream-- > 0)) {
1393 case CODEC_TYPE_VIDEO:
1394 if ((video_index < 0 || wanted_video_stream-- > 0)) {
1402 if (1 /* show_status */) {
1403 dump_format(vs->ic, 0, vs->filename, 0);
1404 dump_stream_info(vs->ic);
1407 /* open the streams */
1408 if (audio_index >= 0) {
1409 stream_component_open(vs, audio_index, ms);
1412 if (video_index >= 0) {
1413 stream_component_open(vs, video_index, ms);
1418 if (vs->video_stream < 0 && vs->audio_stream < 0) {
1419 FFMPEG_DEBUG_AVF("\"%s\": could not open codecs\n",
1424 /* keep the context */
1425 media_stream_data(ms) = vs;
1426 /* set me as driver indicator */
1427 media_stream_driver(ms) = MYSELF;
1437 new_media_ffmpeg_read(media_substream *mss, void *outbuf, size_t length)
1439 VideoState *is = media_stream_data(mss->up); /* was arg */
1441 AVPacket pkt1, *pkt = &pkt1;
1443 /* stuff normally set on the command line */
1444 int64_t start_time = AV_NOPTS_VALUE;
1446 av_init_packet(&flush_pkt);
1447 FFMPEG_CRITICAL("read\n");
1450 /* if seeking requested, we execute it */
1451 if (start_time != AV_NOPTS_VALUE) {
1454 timestamp = start_time;
1455 /* add the stream start time */
1456 if (ic->start_time != AV_NOPTS_VALUE)
1457 timestamp += ic->start_time;
1458 ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
1460 fprintf(stderr, "%s: could not seek to position %0.3f\n",
1461 is->filename, (double)timestamp / AV_TIME_BASE);
1467 if (is->abort_request) {
1468 FFMPEG_DEBUG_AVF("\n");
1471 if (is->paused != is->last_paused) {
1472 is->last_paused = is->paused;
1474 av_read_pause(is->ic);
1476 av_read_play(is->ic);
1478 #ifdef CONFIG_RTSP_DEMUXER
1479 if (is->paused && is->ic->iformat == &rtsp_demuxer) {
1480 /* wait 10 ms to avoid trying to get another packet */
1487 int stream_index= -1;
1488 int64_t seek_target= is->seek_pos;
1490 if (is->video_stream >= 0)
1491 stream_index = is->video_stream;
1492 else if (is->audio_stream >= 0)
1493 stream_index = is->audio_stream;
1494 else if (is->subtitle_stream >= 0)
1495 stream_index = is->subtitle_stream;
1497 if (stream_index >= 0) {
1498 seek_target = av_rescale_q(
1499 seek_target, AV_TIME_BASE_Q,
1500 is->ic->streams[stream_index]->
1504 ret = av_seek_frame(is->ic, stream_index,
1505 seek_target, is->seek_flags);
1507 FFMPEG_DEBUG_AVS("\"%s: \""
1508 "error while seeking\n",
1511 if (is->audio_stream >= 0) {
1512 packet_queue_flush(&is->audioq);
1513 packet_queue_put(&is->audioq, &flush_pkt);
1515 if (is->subtitle_stream >= 0) {
1516 packet_queue_flush(&is->subtitleq);
1517 packet_queue_put(&is->subtitleq, &flush_pkt);
1519 if (is->video_stream >= 0) {
1520 packet_queue_flush(&is->videoq);
1521 packet_queue_put(&is->videoq, &flush_pkt);
1527 /* if the queue are full, no need to read more */
1528 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
1529 is->videoq.size > MAX_VIDEOQ_SIZE ||
1530 is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
1531 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
1532 url_feof(is->ic->pb)
1533 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
1534 url_feof(&is->ic->pb)
1541 ret = av_read_frame(is->ic, pkt);
1544 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
1546 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
1550 usleep(100); /* wait for user event */
1555 if (pkt->stream_index == is->audio_stream) {
1556 packet_queue_put(&is->audioq, pkt);
1557 } else if (pkt->stream_index == is->video_stream) {
1558 packet_queue_put(&is->videoq, pkt);
1559 } else if (pkt->stream_index == is->subtitle_stream) {
1560 packet_queue_put(&is->subtitleq, pkt);
1562 av_free_packet(pkt);
1565 /* wait until the end */
1566 while (!is->abort_request) {
1571 /* disable interrupting */
1572 global_video_state = NULL;
1574 /* close each stream */
1575 if (is->audio_stream >= 0)
1576 stream_component_close(is, is->audio_stream);
1577 if (is->video_stream >= 0)
1578 stream_component_close(is, is->video_stream);
1579 if (is->subtitle_stream >= 0)
1580 stream_component_close(is, is->subtitle_stream);
1582 av_close_input_file(is->ic);
1583 is->ic = NULL; /* safety */
1585 url_set_interrupt_cb(NULL);
1591 event.type = FF_QUIT_EVENT;
1592 event.user.data1 = is;
1593 SDL_PushEvent(&event);
1600 new_media_ffmpeg_rewind(media_substream *mss)
1602 /* rewind the stream to the first frame */
1604 AVFormatContext *avfc;
1606 Lisp_Media_Stream *ms = mss->up;
1611 /* check the integrity of the media stream */
1612 if (media_stream_driver(ms) != MYSELF)
1615 FFMPEG_DEBUG_AVF("rewind substream 0x%lx\n",
1616 (long unsigned int)mss);
1618 /* fetch the format context */
1619 if (!(avfc = media_stream_data(ms)))
1622 si = (long int)mss->substream_data;
1623 avst = avfc->streams[si];
1624 if ((start_time = avst->start_time) < 0) {
1628 FFMPEG_DEBUG_AVF("rewind (idx:%ld) to %lld\n",
1629 si, (long long int)start_time);
1631 /* ... and reset the stream */
1632 res = av_seek_frame(avfc, -1, start_time, AVSEEK_FLAG_BACKWARD);
1635 FFMPEG_DEBUG_AVF("rewind succeeded\n");
1638 FFMPEG_DEBUG_AVF("rewind exitted with %d\n", res);
1645 media_ffmpeg_available_formats(void)
1647 Lisp_Object formats;
1648 AVInputFormat *avif;
1653 avif = first_iformat;
1657 const Lisp_Object fmtname =
1658 Fintern(build_string(avif->name), Qnil);
1659 formats = Fcons(fmtname, formats);