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 AVFormatContext *avfc = NULL;
206 if (avformat_open_input(&avfc, file, NULL, NULL) < 0) {
207 FFMPEG_DEBUG_AVF("opening file failed.\n");
211 /* Retrieve stream information */
212 if (avformat_find_stream_info(avfc, NULL) < 0) {
213 FFMPEG_DEBUG_AVS("opening stream inside file failed.\n");
214 avformat_close_input(&avfc);
223 media_ffmpeg_vio_open(URLContext *h, const char *filename, int flags)
229 media_ffmpeg_vio_read(URLContext *h, unsigned char *buf, int size)
231 media_data *sd = (media_data*)h->priv_data;
233 FFMPEG_DEBUG_AVS("reading %d bytes to 0x%x, respecting seek %ld\n",
234 size, (unsigned int)buf, sd->seek);
236 if ((long int)sd->length <= sd->seek) {
237 FFMPEG_DEBUG_AVS("eof\n");
241 memcpy(buf, sd->data+sd->seek, size);
248 media_ffmpeg_vio_write(URLContext *h, unsigned char *buf, int size)
254 media_ffmpeg_vio_seek(URLContext *h, int64_t pos, int whence)
256 media_data *sd = (media_data*)h->priv_data;
258 FFMPEG_DEBUG_AVS("seeking to %ld via %d\n", (long int)pos, whence);
265 sd->seek = sd->seek+pos;
268 sd->seek = sd->length+pos;
278 media_ffmpeg_vio_close(URLContext *h)
286 /* this is a memory-i/o protocol in case we have to deal with string data */
287 static URLProtocol media_ffmpeg_protocol = {
289 media_ffmpeg_vio_open,
290 media_ffmpeg_vio_read,
291 media_ffmpeg_vio_write,
292 media_ffmpeg_vio_seek,
293 media_ffmpeg_vio_close,
296 /** Size of probe buffer, for guessing file type from file contents. */
297 #define PROBE_BUF_MIN 2048
298 #define PROBE_BUF_MAX 131072
301 media_ffmpeg_open_data(char *data, size_t size)
303 #if defined HAVE_AVFORMAT_ALLOC_CONTEXT
304 AVFormatContext *avfc = avformat_alloc_context();
305 #elif defined HAVE_AV_ALLOC_FORMAT_CONTEXT
306 /* deprecated already, but `people' like Horst still use this */
307 AVFormatContext *avfc = av_alloc_format_context();
309 # error "Your ffmpeg library is too old. Adopt a new one."
310 #endif /* HAVE_AVFORMAT_ALLOC_CONTEXT */
311 AVProbeData *pd = NULL;
312 ByteIOContext *bioctx = NULL;
313 AVInputFormat *fmt = NULL;
314 char file[] = "SXEmff:SXEmacs.mp3\000";
315 media_data *sd = NULL;
317 /* register our virtual i/o */
318 #if defined HAVE_AV_REGISTER_PROTOCOL
319 av_register_protocol(&media_ffmpeg_protocol);
320 #elif defined HAVE_REGISTER_PROTOCOL
321 register_protocol(&media_ffmpeg_protocol);
323 # error "Get a recent ffmpeg or get a life."
326 /* initialise our media_data */
327 sd = xnew_and_zero(media_data);
332 /* register ffmpeg byteio */
333 bioctx = xnew_and_zero(ByteIOContext);
334 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
335 url_fopen(&bioctx, file, URL_RDONLY);
336 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
337 url_fopen(bioctx, file, URL_RDONLY);
339 /* erm, register us at the byteio context */
340 ((URLContext*)(bioctx->opaque))->priv_data = sd;
343 pd = xnew_and_zero(AVProbeData);
348 pd->buf = (void*)sd->data;
349 pd->buf_size = PROBE_BUF_MIN;
350 fmt = av_probe_input_format(pd, 1);
352 /* if still no format found, error */
362 if (av_open_input_stream(&avfc, bioctx, file, fmt, NULL) < 0) {
370 /* Retrieve stream information */
371 if (av_find_stream_info(avfc) < 0) {
383 media_ffmpeg_close(ms_driver_data_t data)
385 AVFormatContext *avfc = (AVFormatContext*)data;
386 FFMPEG_DEBUG_AVF("closing AVFormatContext: 0x%lx\n",
387 (long unsigned int)avfc);
388 if (avfc && avfc->iformat)
389 avformat_close_input(&avfc);
393 media_ffmpeg_analyse_audio(media_substream *mss, AVFormatContext *avfc, int st)
395 mtype_audio_properties *mtap;
396 const char *name = NULL;
397 const char *codec_name = NULL;
398 /* libavformat cruft */
399 AVStream *avst = NULL;
400 AVCodecContext *avcc = NULL;
402 /* unpack the stream and codec context from the container, again */
404 avst = avfc->streams[st];
409 mtap = xnew_and_zero(mtype_audio_properties);
412 if (avfc && avfc->iformat)
413 name = avfc->iformat->name;
414 if (avcc && avcc->codec)
415 codec_name = avcc->codec->name;
418 mtap->codec_name = codec_name;
420 mtap->channels = avcc->channels;
421 mtap->samplerate = avcc->sample_rate;
422 mtap->bitrate = media_ffmpeg_bitrate(avcc);
424 /* samplewidth and framesize */
425 switch (avcc->sample_fmt) {
426 case AV_SAMPLE_FMT_U8:
427 mtap->samplewidth = 8;
428 mtap->framesize = mtap->channels * 1;
429 mtap->msf = sxe_msf_U8;
431 case AV_SAMPLE_FMT_S16:
432 mtap->samplewidth = 16;
433 mtap->framesize = mtap->channels * 2;
434 mtap->msf = sxe_msf_S16;
436 #if defined AV_SAMPLE_FMT_S24
437 case AV_SAMPLE_FMT_S24:
438 mtap->samplewidth = 32;
439 mtap->framesize = mtap->channels * 4;
440 mtap->msf = sxe_msf_S24;
442 #endif /* SAMPLE_FMT_S24 */
443 case AV_SAMPLE_FMT_S32:
444 mtap->samplewidth = 32;
445 mtap->framesize = mtap->channels * 4;
446 mtap->msf = sxe_msf_S32;
448 case AV_SAMPLE_FMT_FLT:
449 mtap->samplewidth = 8*sizeof(float);
450 mtap->framesize = mtap->channels * sizeof(float);
451 mtap->msf = sxe_msf_FLT;
453 case AV_SAMPLE_FMT_NONE:
455 mtap->samplewidth = 0;
459 mtap->endianness = 0;
462 media_substream_type_properties(mss).aprops = mtap;
463 media_substream_data(mss) = (void*)st;
467 media_ffmpeg_analyse_video(media_substream *mss, AVFormatContext *avfc, int st)
469 mtype_video_properties *mtvp;
470 const char *name = NULL;
471 const char *codec_name = NULL;
472 /* libavformat cruft */
473 AVStream *avst = NULL;
474 AVCodecContext *avcc = NULL;
476 /* unpack the stream and codec context from the container, again */
478 avst = avfc->streams[st];
483 mtvp = xnew_and_zero(mtype_video_properties);
486 if (avfc && avfc->iformat)
487 name = avfc->iformat->name;
488 if (avcc && avcc->codec)
489 codec_name = avcc->codec->name;
492 mtvp->codec_name = codec_name;
494 mtvp->bitrate = avcc->bit_rate;
495 mtvp->width = avcc->width;
496 mtvp->height = avcc->height;
497 mtvp->aspect_num = avcc->sample_aspect_ratio.num;
498 mtvp->aspect_den = avcc->sample_aspect_ratio.den;
501 mtvp->endianness = 0;
504 media_substream_type_properties(mss).vprops = mtvp;
505 media_substream_data(mss) = (void*)st;
508 /* main analysis function */
509 static ms_driver_data_t
510 media_ffmpeg_open(Lisp_Media_Stream *ms)
513 media_substream *mss;
514 /* libavformat stuff */
515 AVFormatContext *avfc = NULL;
516 AVStream *avst = NULL;
517 AVCodecContext *avcc = NULL;
523 switch (media_stream_kind(ms)) {
525 mkind_file_properties *mkfp = NULL;
530 mkfp = media_stream_kind_properties(ms).fprops;
531 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
532 ALLOCA, (file, file_len), Qnil);
533 SXE_SET_UNUSED(file_len);
535 avfc = media_ffmpeg_open_file(file);
537 media_stream_set_meths(ms, NULL);
538 media_stream_driver(ms) = MDRIVER_UNKNOWN;
542 /* store the filesize */
543 mkfp->filesize = avio_size(avfc->pb);
547 mkind_string_properties *mksp = NULL;
552 mksp = media_stream_kind_properties(ms).sprops;
553 data = mksp->stream_data;
555 avfc = media_ffmpeg_open_data(data, size);
558 media_stream_set_meths(ms, NULL);
559 media_stream_driver(ms) = MDRIVER_UNKNOWN;
567 case NUMBER_OF_MEDIA_KINDS:
573 /* check if there is at least one usable stream */
574 for (size_t st = 0; st < avfc->nb_streams; st++) {
575 avst = avfc->streams[st];
578 avcc->codec_id != CODEC_ID_NONE &&
579 avcc->codec_type != AVMEDIA_TYPE_DATA &&
580 (avc = avcodec_find_decoder(avcc->codec_id)) &&
581 (avc && (avcodec_open(avcc, avc) >= 0))) {
583 /* create a substream */
584 mss = make_media_substream_append(ms);
586 switch ((unsigned int)avcc->codec_type) {
587 case AVMEDIA_TYPE_VIDEO:
588 /* assign substream props */
589 media_substream_type(mss) = MTYPE_VIDEO;
590 media_ffmpeg_analyse_video(mss, avfc, st);
592 case AVMEDIA_TYPE_AUDIO:
593 /* assign substream props */
594 media_substream_type(mss) = MTYPE_AUDIO;
595 media_ffmpeg_analyse_audio(mss, avfc, st);
596 /* set some stream handlers */
597 media_stream_set_meths(ms, media_ffmpeg);
599 case AVMEDIA_TYPE_DATA:
600 media_substream_type(mss) = MTYPE_IMAGE;
603 media_substream_type(mss) = MTYPE_UNKNOWN;
609 /* keep the format context */
610 media_stream_data(ms) = avfc;
612 /* set me as driver indicator */
613 media_stream_driver(ms) = MYSELF;
620 handle_packet(AVFormatContext *avfc, AVPacket *pkt)
625 int ret, got_picture;
627 st = avfc->streams[pkt->stream_index];
629 /* XXX: allocate picture correctly */
630 avcodec_get_frame_defaults(&picture);
632 ret = avcodec_decode_video(
633 st->codec, &picture, &got_picture, pkt->data, pkt->size);
641 FFMPEG_DEBUG_AVF("got video frame\n");
651 media_ffmpeg_read(media_substream *mss, void *outbuf, size_t length)
653 /* read at most `length' frames into `outbuf' */
654 /* convert them to internal format */
656 Lisp_Media_Stream *ms = mss->up;
657 mtype_audio_properties *mtap;
658 media_sample_format_t *fmt;
660 AVFormatContext *avfc;
662 AVCodecContext *avcc;
666 /* the size we present here, is _not_ the size we want, however
667 * ffmpeg is quite pedantic about the buffer size,
668 * we just pass the least possible value here to please him */
669 int size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
672 long int bufseek = 0, si = -1;
673 int declen, dec, rf_status = 0;
675 /* check the integrity of the media stream */
676 if (media_stream_driver(ms) != MYSELF)
679 /* fetch the format context */
680 avfc = media_stream_data(ms);
685 si = (long int)mss->substream_data;
686 avst = avfc->streams[si];
690 /* unpack the substream */
691 if ((mtap = media_substream_type_properties(mss).aprops) == NULL) {
692 FFMPEG_DEBUG_AVS("stream information missing. Uh Oh.\n");
696 /* fetch audio info */
697 framesize = mtap->framesize;
700 /* initialise the packet */
701 pkt.pts = pkt.dts = pkt.size = 0;
702 FFMPEG_DEBUG_AVF("initialised packet: "
703 "pts:%lld dts:%lld psz:%d\n",
704 (long long int)pkt.pts,
705 (long long int)pkt.dts,
708 /* read a frame and decode it */
709 while ((size_t)bufseek <= length*framesize &&
710 (rf_status = av_read_frame(avfc, &pkt)) >= 0) {
711 if (pkt.stream_index != si) {
712 FFMPEG_DEBUG_AVF("SKIP reason: "
713 "sought after stream %ld, got %ld\n",
715 (long int)pkt.stream_index);
716 handle_packet(avfc, &pkt);
720 FFMPEG_DEBUG_AVF("read frame: "
721 "pts:%lld dts:%lld psz:%d\n",
722 (long long int)pkt.pts,
723 (long long int)pkt.dts,
727 /* decode the demuxed packet */
728 #ifdef HAVE_AVCODEC_DECODE_AUDIO2
729 /* prefer decode_audio2() if available */
730 size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
731 declen = avcodec_decode_audio2(
732 avcc, (void*)((char*)outbuf+bufseek),
733 &size, pkt.data, pkt.size);
734 #elif defined HAVE_AVCODEC_DECODE_AUDIO
735 declen = avcodec_decode_audio(
736 avcc, (void*)((char*)outbuf+bufseek),
737 &size, pkt.data, pkt.size);
742 if (dec > 0 && size > 0) {
743 FFMPEG_DEBUG_AVF("pts:%lld dts:%lld psz:%d s:%d d:%d\n",
744 (long long int)pkt.pts,
745 (long long int)pkt.dts,
746 pkt.size, size, declen);
748 /* memcpy(outbuf+bufseek, (char*)buffer, size); */
752 FFMPEG_DEBUG_AVF("packet state: "
753 "pts:%lld dts:%lld psz:%d\n",
754 (long long int)pkt.pts,
755 (long long int)pkt.dts,
757 av_free_packet(&pkt);
759 av_free_packet(&pkt);
761 FFMPEG_DEBUG_AVF("finished reading, bufseek=%ld, rf_status=%ld\n",
762 (long int)bufseek, (long int)rf_status);
764 /* convert the pig */
765 size = bufseek/framesize;
766 MEDIA_SAMPLE_FORMAT_UPSAMPLE(fmt)(outbuf, outbuf, size*mtap->channels);
773 media_ffmpeg_rewind(media_substream *mss)
775 /* rewind the stream to the first frame */
777 AVFormatContext *avfc;
779 Lisp_Media_Stream *ms = mss->up;
784 /* check the integrity of the media stream */
785 if (media_stream_driver(ms) != MYSELF)
788 FFMPEG_DEBUG_AVF("rewind substream 0x%lx\n",
789 (long unsigned int)mss);
791 /* fetch the format context */
792 if (!(avfc = media_stream_data(ms)))
795 si = (long int)mss->substream_data;
796 avst = avfc->streams[si];
797 if ((start_time = avst->start_time) < 0) {
801 FFMPEG_DEBUG_AVF("rewind (idx:%ld) to %lld\n",
802 si, (long long int)start_time);
804 /* ... and reset the stream */
805 res = av_seek_frame(avfc, si, AV_NOPTS_VALUE, AVSEEK_FLAG_BACKWARD);
808 FFMPEG_DEBUG_AVF("rewind succeeded\n");
811 FFMPEG_DEBUG_AVF("rewind exitted with %d\n", res);
818 * the size must be big enough to compensate the hardware audio buffersize size
820 #define SAMPLE_ARRAY_SIZE (2*65536)
821 #define VIDEO_PICTURE_QUEUE_SIZE 1
822 #define SUBPICTURE_QUEUE_SIZE 4
823 #define AUDIO_DIFF_AVG_NB 20
824 #define SDL_AUDIO_BUFFER_SIZE 1024
826 #define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
827 #define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
828 #define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
830 #define FF_ALLOC_EVENT 0
831 #define FF_REFRESH_EVENT 1
832 #define FF_QUIT_EVENT 2
834 typedef struct PacketQueue {
835 AVPacketList *first_pkt, *last_pkt;
839 struct sxe_semaphore_s sem;
842 typedef struct VideoPicture {
843 /* presentation time stamp for this picture */
846 int width, height; /* source height & width */
850 typedef struct SubPicture {
851 double pts; /* presentation time stamp for this picture */
855 typedef struct VideoState {
858 AVInputFormat *iformat;
867 int dtg_active_format;
872 double external_clock; /* external clock base */
873 int64_t external_clock_time;
876 double audio_diff_cum; /* used for AV difference average computation */
877 double audio_diff_avg_coef;
878 double audio_diff_threshold;
879 int audio_diff_avg_count;
882 int audio_hw_buf_size;
883 /* samples output by the codec. we reserve more space for avsync
885 uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]
886 /* fixme, this is very gcc centric, what's aligned(x) in icc? */
887 __attribute__((aligned(16)));
888 unsigned int audio_buf_size; /* in bytes */
889 int audio_buf_index; /* in bytes */
891 uint8_t *audio_pkt_data;
894 int show_audio; /* if true, display audio samples */
895 int16_t sample_array[SAMPLE_ARRAY_SIZE];
896 int sample_array_index;
901 int subtitle_stream_changed;
902 AVStream *subtitle_st;
903 PacketQueue subtitleq;
904 SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
905 int subpq_size, subpq_rindex, subpq_windex;
906 struct sxe_semaphore_s subpq_sem;
909 double frame_last_pts;
910 double frame_last_delay;
911 /* pts of last decoded frame / predicted pts of next decoded frame */
916 /* current displayed pts (different from video_clock
917 * if frame fifos are used */
918 double video_current_pts;
919 /* time (av_gettime) at which we updated video_current_pts - used
920 * to have running video pts */
921 int64_t video_current_pts_time;
922 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
923 int pictq_size, pictq_rindex, pictq_windex;
924 struct sxe_semaphore_s pictq_sem;
926 /* QETimer *video_timer; */
930 int width, height, xleft, ytop;
933 /* since we have only one decoding thread, we can use a global
934 variable instead of a thread local variable */
937 /* packet queue handling */
939 packet_queue_init(PacketQueue *q)
941 memset(q, 0, sizeof(PacketQueue));
942 SXE_SEMAPH_INIT(&q->sem);
946 packet_queue_flush(PacketQueue *q)
948 AVPacketList *pkt, *pkt1;
950 SXE_SEMAPH_LOCK(&q->sem);
951 for (pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
953 av_free_packet(&pkt->pkt);
960 SXE_SEMAPH_UNLOCK(&q->sem);
964 packet_queue_end(PacketQueue *q)
966 packet_queue_flush(q);
967 SXE_SEMAPH_FINI(&q->sem);
971 packet_queue_put(PacketQueue *q, AVPacket *pkt)
975 /* duplicate the packet */
976 if (pkt!=&flush_pkt && av_dup_packet(pkt) < 0)
979 pkt1 = av_malloc(sizeof(AVPacketList));
986 SXE_SEMAPH_LOCK(&q->sem);
992 q->last_pkt->next = pkt1;
995 q->size += pkt1->pkt.size;
996 /* XXX: should duplicate packet data in DV case */
997 SXE_SEMAPH_SIGNAL(&q->sem);
998 SXE_SEMAPH_UNLOCK(&q->sem);
1003 packet_queue_abort(PacketQueue *q)
1005 SXE_SEMAPH_LOCK(&q->sem);
1007 q->abort_request = 1;
1009 SXE_SEMAPH_SIGNAL(&q->sem);
1010 SXE_SEMAPH_UNLOCK(&q->sem);
1013 /* return < 0 if aborted, 0 if no packet and > 0 if packet. */
1015 packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
1016 __attribute__((unused));
1019 packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
1024 SXE_SEMAPH_LOCK(&q->sem);
1027 if (q->abort_request) {
1032 pkt1 = q->first_pkt;
1034 q->first_pkt = pkt1->next;
1038 q->size -= pkt1->pkt.size;
1043 } else if (!block) {
1047 SXE_SEMAPH_WAIT(&q->sem);
1050 SXE_SEMAPH_UNLOCK(&q->sem);
1054 static uint64_t global_video_pkt_pts = AV_NOPTS_VALUE;
1057 my_get_buffer(struct AVCodecContext *c, AVFrame *pic)
1059 int ret= avcodec_default_get_buffer(c, pic);
1060 uint64_t *pts= av_malloc(sizeof(uint64_t));
1061 *pts= global_video_pkt_pts;
1067 my_release_buffer(struct AVCodecContext *c, AVFrame *pic)
1069 if(pic) av_freep(&pic->opaque);
1070 avcodec_default_release_buffer(c, pic);
1075 stream_component_open(VideoState *is, int stream_index, Lisp_Media_Stream *ms)
1078 media_substream *mss = NULL;
1079 AVFormatContext *ic = is->ic;
1080 AVCodecContext *enc;
1083 if (stream_index < 0 || (size_t)stream_index >= ic->nb_streams) {
1086 enc = ic->streams[stream_index]->codec;
1088 /* prepare audio output */
1089 if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
1091 wanted_spec.freq = enc->sample_rate;
1092 wanted_spec.format = AUDIO_S16SYS;
1094 /* hack for AC3. XXX: suppress that */
1095 if (enc->channels > 2)
1098 wanted_spec.channels = enc->channels;
1099 wanted_spec.silence = 0;
1100 wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1101 wanted_spec.callback = sdl_audio_callback;
1102 wanted_spec.userdata = is;
1104 is->audio_hw_buf_size = 0 /* spec.size */;
1107 codec = avcodec_find_decoder(enc->codec_id);
1108 enc->debug_mv = 0 /* debug_mv */;
1109 enc->debug = 0 /* debug */;
1110 enc->workaround_bugs = 0 /* workaround_bugs */;
1111 enc->lowres = 0 /* lowres */;
1113 enc->flags |= CODEC_FLAG_EMU_EDGE;
1114 enc->idct_algo = FF_IDCT_AUTO; /* idct; */
1116 enc->flags2 |= CODEC_FLAG2_FAST;
1117 enc->skip_frame = AVDISCARD_DEFAULT; /* skip_frame; */
1118 enc->skip_idct = AVDISCARD_DEFAULT; /* skip_idct; */
1119 enc->skip_loop_filter = AVDISCARD_DEFAULT; /* skip_loop_filter; */
1121 enc->error_resilience = FF_ER_CAREFUL; /* error_resilience; */
1123 enc->error_concealment = 3; /* error_concealment; */
1125 avcodec_open(enc, codec) < 0)
1127 if (1 /* thread_count */ > 1)
1128 avcodec_thread_init(enc, 1 /*thread_count*/);
1129 enc->thread_count= 1 /* thread_count */;
1131 /* create a substream */
1132 mss = make_media_substream_append(ms);
1134 switch ((unsigned int)enc->codec_type) {
1135 case AVMEDIA_TYPE_AUDIO:
1136 is->audio_stream = stream_index;
1137 is->audio_st = ic->streams[stream_index];
1138 is->audio_buf_size = 0;
1139 is->audio_buf_index = 0;
1141 /* init averaging filter */
1142 is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
1143 is->audio_diff_avg_count = 0;
1144 /* since we do not have a precise anough audio fifo fullness,
1145 we correct audio sync only if larger than this threshold */
1146 is->audio_diff_threshold =
1147 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
1149 memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
1150 packet_queue_init(&is->audioq);
1152 media_substream_type(mss) = MTYPE_AUDIO;
1153 media_ffmpeg_analyse_audio(mss, is->ic, stream_index);
1155 case AVMEDIA_TYPE_VIDEO:
1156 is->video_stream = stream_index;
1157 is->video_st = ic->streams[stream_index];
1159 is->frame_last_delay = 40e-3;
1161 int64_t tmp = av_gettime();
1162 is->frame_timer = (double)tmp / 1000000.0f;
1164 is->video_current_pts_time = av_gettime();
1166 packet_queue_init(&is->videoq);
1167 is->video_tid = 0 /* SDL_CreateThread(video_thread, is) */;
1169 enc-> get_buffer= my_get_buffer;
1170 enc->release_buffer= my_release_buffer;
1172 media_substream_type(mss) = MTYPE_VIDEO;
1173 media_ffmpeg_analyse_video(mss, is->ic, stream_index);
1175 case AVMEDIA_TYPE_SUBTITLE:
1176 is->subtitle_stream = stream_index;
1177 is->subtitle_st = ic->streams[stream_index];
1178 packet_queue_init(&is->subtitleq);
1180 is->subtitle_tid = 0 /*SDL_CreateThread(subtitle_thread, is)*/;
1189 stream_component_close(VideoState *is, int stream_index)
1191 AVFormatContext *ic = is->ic;
1192 AVCodecContext *enc;
1194 if (stream_index < 0 || (size_t)stream_index >= ic->nb_streams) {
1197 enc = ic->streams[stream_index]->codec;
1199 switch ((unsigned int)enc->codec_type) {
1200 case AVMEDIA_TYPE_AUDIO:
1201 packet_queue_abort(&is->audioq);
1205 packet_queue_end(&is->audioq);
1207 case AVMEDIA_TYPE_VIDEO:
1208 packet_queue_abort(&is->videoq);
1210 /* note: we also signal this mutex to make sure we deblock the
1211 video thread in all cases */
1212 SXE_SEMAPH_LOCK(&is->pictq_sem);
1213 SXE_SEMAPH_SIGNAL(&is->pictq_sem);
1214 SXE_SEMAPH_UNLOCK(&is->pictq_sem);
1216 SDL_WaitThread(is->video_tid, NULL);
1218 packet_queue_end(&is->videoq);
1220 case AVMEDIA_TYPE_SUBTITLE:
1221 packet_queue_abort(&is->subtitleq);
1223 /* note: we also signal this mutex to make sure we deblock the
1224 video thread in all cases */
1225 SXE_SEMAPH_LOCK(&is->subpq_sem);
1226 is->subtitle_stream_changed = 1;
1228 SXE_SEMAPH_SIGNAL(&is->subpq_sem);
1229 SXE_SEMAPH_UNLOCK(&is->subpq_sem);
1231 SDL_WaitThread(is->subtitle_tid, NULL);
1233 packet_queue_end(&is->subtitleq);
1240 switch ((unsigned int)enc->codec_type) {
1241 case AVMEDIA_TYPE_AUDIO:
1242 is->audio_st = NULL;
1243 is->audio_stream = -1;
1245 case AVMEDIA_TYPE_VIDEO:
1246 is->video_st = NULL;
1247 is->video_stream = -1;
1249 case AVMEDIA_TYPE_SUBTITLE:
1250 is->subtitle_st = NULL;
1251 is->subtitle_stream = -1;
1259 dump_stream_info(const AVFormatContext *s)
1261 static const char *keys[] = {
1262 "track", "title", "author", "copyright", "comment",
1263 "album", "date", "genre"
1265 static const size_t nkeys = sizeof(keys)/sizeof(keys[0]);
1267 AVDictionaryEntry *curr = NULL;
1268 if (! s->metadata) {
1269 fprintf(stderr, "No metadata\n");
1273 for (i = 0; i < nkeys; ++i ) {
1274 curr = av_dict_get(s->metadata,
1277 AV_DICT_IGNORE_SUFFIX);
1279 fprintf(stderr, "%s: %s\n", curr->key, curr->value);
1284 AV_SYNC_AUDIO_MASTER, /* default choice */
1285 AV_SYNC_VIDEO_MASTER,
1286 AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
1290 stream_open(char *filename, size_t filelen)
1292 VideoState *is = xnew(VideoState);
1293 AVFormatParameters params, *ap = ¶ms;
1296 is->filename = filename;
1297 is->filelen = filelen;
1298 is->iformat = av_find_input_format("fmt");
1302 /* initialise some semaphores */
1303 SXE_SEMAPH_INIT(&is->pictq_sem);
1304 SXE_SEMAPH_INIT(&is->subpq_sem);
1306 is->av_sync_type = AV_SYNC_AUDIO_MASTER;
1307 is->parse_tid = 0; /* SDL_CreateThread(decode_thread, is); */
1309 memset(ap, 0, sizeof(*ap));
1310 /* we force a pause when starting an RTSP stream */
1311 ap->initial_pause = 1;
1313 ap->width = 0; /* frame_width; */
1314 ap->height= 0; /* frame_height; */
1315 ap->time_base= (AVRational){1, 25};
1316 ap->pix_fmt = PIX_FMT_NONE; /* frame_pix_fmt; */
1318 err = avformat_open_input(&is->ic, is->filename, is->iformat, NULL /*ap*/);
1319 if (UNLIKELY(err < 0)) {
1320 FFMPEG_DEBUG_AVF("Could not open \"%s\" (errno %d)\n",
1332 /* main analysis function */
1333 static ms_driver_data_t
1334 new_media_ffmpeg_open(Lisp_Media_Stream *ms)
1336 /* the final result */
1337 VideoState *vs = NULL;
1338 int err = 0, use_play = 0;
1339 int wanted_audio_stream = 0;
1340 int wanted_video_stream = 0;
1341 int video_index = -1, audio_index = -1;
1342 mkind_file_properties *mkfp = NULL;
1349 if (media_stream_kind(ms) != MKIND_FILE) {
1354 mkfp = media_stream_kind_properties(ms).fprops;
1355 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
1356 MALLOC, (file, file_len), Qnil);
1357 if (UNLIKELY((vs = stream_open(file, file_len)) == NULL)) {
1358 media_stream_set_meths(ms, NULL);
1359 media_stream_driver(ms) = MDRIVER_UNKNOWN;
1363 #ifdef CONFIG_RTSP_DEMUXER
1364 use_play = (ic->iformat == &rtsp_demuxer);
1369 if (1 /* genpts */) {
1370 vs->ic->flags |= AVFMT_FLAG_GENPTS;
1374 err = avformat_find_stream_info(vs->ic, NULL);
1376 FFMPEG_DEBUG_AVF("\"%s\": "
1377 "could not find codec parameters\n",
1382 * ffplay maybe should not use url_feof() to test for the end */
1383 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
1384 vs->ic->pb->eof_reached = 0;
1385 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
1386 vs->ic->pb.eof_reached = 0;
1390 /* now we can begin to play (RTSP stream only) */
1391 av_read_play(vs->ic);
1394 err = avformat_find_stream_info(vs->ic, NULL);
1396 FFMPEG_DEBUG_AVF("\"%s\": "
1397 "could not find codec parameters\n",
1403 for (size_t i = 0; i < vs->ic->nb_streams; i++) {
1404 AVCodecContext *enc = vs->ic->streams[i]->codec;
1405 switch ((unsigned int)enc->codec_type) {
1406 case AVMEDIA_TYPE_AUDIO:
1407 if ((audio_index < 0 || wanted_audio_stream-- > 0)) {
1411 case AVMEDIA_TYPE_VIDEO:
1412 if ((video_index < 0 || wanted_video_stream-- > 0)) {
1420 if (1 /* show_status */) {
1421 av_dump_format(vs->ic, 0, vs->filename, 0);
1422 dump_stream_info(vs->ic);
1425 /* open the streams */
1426 if (audio_index >= 0) {
1427 stream_component_open(vs, audio_index, ms);
1430 if (video_index >= 0) {
1431 stream_component_open(vs, video_index, ms);
1436 if (vs->video_stream < 0 && vs->audio_stream < 0) {
1437 FFMPEG_DEBUG_AVF("\"%s\": could not open codecs\n",
1442 /* keep the context */
1443 media_stream_data(ms) = vs;
1444 /* set me as driver indicator */
1445 media_stream_driver(ms) = MYSELF;
1455 new_media_ffmpeg_read(media_substream *mss, void *outbuf, size_t length)
1457 VideoState *is = media_stream_data(mss->up); /* was arg */
1459 AVPacket pkt1, *pkt = &pkt1;
1461 /* stuff normally set on the command line */
1462 int64_t start_time = AV_NOPTS_VALUE;
1464 av_init_packet(&flush_pkt);
1465 FFMPEG_CRITICAL("read\n");
1468 /* if seeking requested, we execute it */
1469 if (start_time != AV_NOPTS_VALUE) {
1472 timestamp = start_time;
1473 /* add the stream start time */
1474 if (ic->start_time != AV_NOPTS_VALUE)
1475 timestamp += ic->start_time;
1476 ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
1478 fprintf(stderr, "%s: could not seek to position %0.3f\n",
1479 is->filename, (double)timestamp / AV_TIME_BASE);
1485 if (is->abort_request) {
1486 FFMPEG_DEBUG_AVF("\n");
1489 if (is->paused != is->last_paused) {
1490 is->last_paused = is->paused;
1492 av_read_pause(is->ic);
1494 av_read_play(is->ic);
1496 #ifdef CONFIG_RTSP_DEMUXER
1497 if (is->paused && is->ic->iformat == &rtsp_demuxer) {
1498 /* wait 10 ms to avoid trying to get another packet */
1505 int stream_index= -1;
1506 int64_t seek_target= is->seek_pos;
1508 if (is->video_stream >= 0)
1509 stream_index = is->video_stream;
1510 else if (is->audio_stream >= 0)
1511 stream_index = is->audio_stream;
1512 else if (is->subtitle_stream >= 0)
1513 stream_index = is->subtitle_stream;
1515 if (stream_index >= 0) {
1516 seek_target = av_rescale_q(
1517 seek_target, AV_TIME_BASE_Q,
1518 is->ic->streams[stream_index]->
1522 ret = av_seek_frame(is->ic, stream_index,
1523 seek_target, is->seek_flags);
1525 FFMPEG_DEBUG_AVS("\"%s: \""
1526 "error while seeking\n",
1529 if (is->audio_stream >= 0) {
1530 packet_queue_flush(&is->audioq);
1531 packet_queue_put(&is->audioq, &flush_pkt);
1533 if (is->subtitle_stream >= 0) {
1534 packet_queue_flush(&is->subtitleq);
1535 packet_queue_put(&is->subtitleq, &flush_pkt);
1537 if (is->video_stream >= 0) {
1538 packet_queue_flush(&is->videoq);
1539 packet_queue_put(&is->videoq, &flush_pkt);
1545 /* if the queue are full, no need to read more */
1546 if (is->audioq.size > MAX_AUDIOQ_SIZE ||
1547 is->videoq.size > MAX_VIDEOQ_SIZE ||
1548 is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
1549 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
1550 url_feof(is->ic->pb)
1551 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
1552 url_feof(&is->ic->pb)
1559 ret = av_read_frame(is->ic, pkt);
1562 #if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR
1564 #elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR
1568 usleep(100); /* wait for user event */
1573 if (pkt->stream_index == is->audio_stream) {
1574 packet_queue_put(&is->audioq, pkt);
1575 } else if (pkt->stream_index == is->video_stream) {
1576 packet_queue_put(&is->videoq, pkt);
1577 } else if (pkt->stream_index == is->subtitle_stream) {
1578 packet_queue_put(&is->subtitleq, pkt);
1580 av_free_packet(pkt);
1583 /* wait until the end */
1584 while (!is->abort_request) {
1590 /* close each stream */
1591 if (is->audio_stream >= 0)
1592 stream_component_close(is, is->audio_stream);
1593 if (is->video_stream >= 0)
1594 stream_component_close(is, is->video_stream);
1595 if (is->subtitle_stream >= 0)
1596 stream_component_close(is, is->subtitle_stream);
1598 avformat_close_input(&is->ic);
1599 is->ic = NULL; /* safety */
1601 url_set_interrupt_cb(NULL);
1607 event.type = FF_QUIT_EVENT;
1608 event.user.data1 = is;
1609 SDL_PushEvent(&event);
1616 new_media_ffmpeg_rewind(media_substream *mss)
1618 /* rewind the stream to the first frame */
1620 AVFormatContext *avfc;
1622 Lisp_Media_Stream *ms = mss->up;
1627 /* check the integrity of the media stream */
1628 if (media_stream_driver(ms) != MYSELF)
1631 FFMPEG_DEBUG_AVF("rewind substream 0x%lx\n",
1632 (long unsigned int)mss);
1634 /* fetch the format context */
1635 if (!(avfc = media_stream_data(ms)))
1638 si = (long int)mss->substream_data;
1639 avst = avfc->streams[si];
1640 if ((start_time = avst->start_time) < 0) {
1644 FFMPEG_DEBUG_AVF("rewind (idx:%ld) to %lld\n",
1645 si, (long long int)start_time);
1647 /* ... and reset the stream */
1648 res = av_seek_frame(avfc, -1, start_time, AVSEEK_FLAG_BACKWARD);
1651 FFMPEG_DEBUG_AVF("rewind succeeded\n");
1654 FFMPEG_DEBUG_AVF("rewind exitted with %d\n", res);
1661 media_ffmpeg_available_formats(void)
1663 Lisp_Object formats;
1664 AVInputFormat *avif;
1669 avif = first_iformat;
1673 const Lisp_Object fmtname =
1674 Fintern(build_string(avif->name), Qnil);
1675 formats = Fcons(fmtname, formats);