From: Nelson Ferreira Date: Thu, 31 Dec 2015 19:39:54 +0000 (-0500) Subject: Final set of changes for a working ffmpeg. X-Git-Tag: v22.1.16~6^2 X-Git-Url: http://cgit.sxemacs.org/?p=sxemacs;a=commitdiff_plain;h=32e915e5dc4fea21550f0f97a3d526229182f374;ds=sidebyside Final set of changes for a working ffmpeg. There are a couple of edges to polish but "works for me" now. * src/media/media-ffmpeg.c (media_ffmpeg_read): Use avcodec_decode_audio3 if available. More work is needed to use avcodec_decod_audio4 because it uses frames which would need to then be copied to the output buffer. (my_get_buffer): Use avcodec_default_get_buffer2. (my_release_buffer): No longer needed. (stream_component_open): Properly set the thread count and use avcodec_open2. Set get_buffer2 to my_get_buffer since we are using the new interface. (media_ffmpeg_available_formats): Use av_iformat_next. (stream_open): Defer setting codec options to a later better understanding of ffmpeg (keep #if 0 the old). (new_media_ffmpeg_open): Use only the most recent AVIOContext access method to set eof_reached. If we get issues reported we'll revisit. (new_media_ffmpeg_read): Use avio_eof and the most error field of AVIOContext instead of furl_feof. Do not unset the interrupt callback for now. We may need to revisit the reset of the callback later. * m4/sxe-mm.m4 (SXE_CHECK_FFMPEG_LIBS): Properly check for the avcodec_decode_audio* and define corresponding HAVE_AVCODEC_AUDIO*. Also check for av_iformat_next. (SXE_MM_CHECK_FFMPEG): Check at least one avcodec_decode_audio is available and av_iformat_next. Signed-off-by: Nelson Ferreira --- diff --git a/m4/sxe-mm.m4 b/m4/sxe-mm.m4 index ef8d3a8..92e873d 100644 --- a/m4/sxe-mm.m4 +++ b/m4/sxe-mm.m4 @@ -366,7 +366,9 @@ AC_DEFUN([SXE_MM_CHECK_FFMPEG], [ fi ## make sure either decode_audio is there - if test "$ac_cv_lib_avcodec_avcodec_decode_audio4" = "yes"; then + if test "$ac_cv_lib_avcodec_avcodec_decode_audio" = "yes" -o \ + "$ac_cv_lib_avcodec_avcodec_decode_audio2" = "yes" -o \ + "$ac_cv_lib_avcodec_avcodec_decode_audio3" = "yes"; then sxe_cv_feat_ffmpeg_decoders="yes" fi @@ -381,6 +383,7 @@ AC_DEFUN([SXE_MM_CHECK_FFMPEG], [ "$ac_cv_lib_avformat_avformat_close_input" = "yes" -a \ "$ac_cv_lib_avformat_avformat_find_stream_info" = "yes" -a \ "$ac_cv_lib_avformat_av_probe_input_format" = "yes" -a \ + "$ac_cv_lib_avformat_av_iformat_next" = "yes" -a \ "$ac_cv_lib_avformat_av_read_frame" = "yes" -a \ "$ac_cv_lib_avformat_av_seek_frame" = "yes" -a \ "$ac_cv_lib_avformat_av_register_all" = "yes" -a \ @@ -432,11 +435,15 @@ AC_DEFUN([SXE_CHECK_FFMPEG_LIBS], [dnl AC_CHECK_LIB([avcodec], [avcodec_find_decoder], [:], [:], [${FFMPEG_LIBS}]) AC_CHECK_LIB([avcodec], [avcodec_open2], [:], [:], [${FFMPEG_LIBS}]) + AC_CHECK_LIB([avcodec], [avcodec_decode_audio], [:], [:], [${FFMPEG_LIBS}]) + AC_CHECK_LIB([avcodec], [avcodec_decode_audio2], [:], [:], [${FFMPEG_LIBS}]) + AC_CHECK_LIB([avcodec], [avcodec_decode_audio3], [:], [:], [${FFMPEG_LIBS}]) AC_CHECK_LIB([avcodec], [avcodec_decode_audio4], [:], [:], [${FFMPEG_LIBS}]) AC_CHECK_LIB([avformat], [avformat_open_input], [:], [:], [${FFMPEG_LIBS}]) AC_CHECK_LIB([avformat], [avformat_close_input], [:], [:], [${FFMPEG_LIBS}]) AC_CHECK_LIB([avformat], [avformat_find_stream_info], [:], [:], [${FFMPEG_LIBS}]) + AC_CHECK_LIB([avformat], [av_iformat_next], [:], [:], [${FFMPEG_LIBS}]) AC_CHECK_LIB([avformat], [av_probe_input_format], [:], [:], [${FFMPEG_LIBS}]) AC_CHECK_LIB([avformat], [av_read_frame], [:], [:], [${FFMPEG_LIBS}]) AC_CHECK_LIB([avformat], [av_seek_frame], [:], [:], [${FFMPEG_LIBS}]) @@ -450,6 +457,22 @@ AC_DEFUN([SXE_CHECK_FFMPEG_LIBS], [dnl AC_CHECK_LIB([avutil], [av_dict_get], [:], [:], [${FFMPEG_LIBS}]) + if test "$ac_cv_lib_avcodec_avcodec_decode_audio" = "yes"; then + AC_DEFINE([HAVE_AVCODEC_DECODE_AUDIO], [1], + [Define to 1 if avcodec_decode_audio is usable.]) + fi + if test "$ac_cv_lib_avcodec_avcodec_decode_audio2" = "yes"; then + AC_DEFINE([HAVE_AVCODEC_DECODE_AUDIO2], [1], + [Define to 1 if avcodec_decode_audio2 is usable.]) + fi + if test "$ac_cv_lib_avcodec_avcodec_decode_audio3" = "yes"; then + AC_DEFINE([HAVE_AVCODEC_DECODE_AUDIO3], [1], + [Define to 1 if avcodec_decode_audio is usable.]) + fi + if test "$ac_cv_lib_avcodec_avcodec_decode_audio4" = "yes"; then + AC_DEFINE([HAVE_AVCODEC_DECODE_AUDIO4], [1], + [Define to 1 if avcodec_decode_audio is usable.]) + fi ## restore configuration SXE_RESTORE_LIBS diff --git a/src/media/media-ffmpeg.c b/src/media/media-ffmpeg.c index d7fa9f9..559b2e9 100644 --- a/src/media/media-ffmpeg.c +++ b/src/media/media-ffmpeg.c @@ -681,7 +681,13 @@ media_ffmpeg_read(media_substream *mss, void *outbuf, size_t length) dec = pkt.size; /* decode the demuxed packet */ -#ifdef HAVE_AVCODEC_DECODE_AUDIO2 +#ifdef HAVE_AVCODEC_DECODE_AUDIO3 +/* prefer decode_audio3() if available */ + size = AVCODEC_MAX_AUDIO_FRAME_SIZE; + declen = avcodec_decode_audio3( + avcc, (void*)((char*)outbuf+bufseek), + &size, &pkt); +#elif HAVE_AVCODEC_DECODE_AUDIO2 /* prefer decode_audio2() if available */ size = AVCODEC_MAX_AUDIO_FRAME_SIZE; declen = avcodec_decode_audio2( @@ -1012,23 +1018,15 @@ packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) static uint64_t global_video_pkt_pts = AV_NOPTS_VALUE; static int -my_get_buffer(struct AVCodecContext *c, AVFrame *pic) +my_get_buffer(struct AVCodecContext *c, AVFrame *pic, int flags) { - int ret= avcodec_default_get_buffer(c, pic); + int ret= avcodec_default_get_buffer2(c, pic, flags); uint64_t *pts= av_malloc(sizeof(uint64_t)); *pts= global_video_pkt_pts; pic->opaque= pts; return ret; } -static void -my_release_buffer(struct AVCodecContext *c, AVFrame *pic) -{ - if(pic) av_freep(&pic->opaque); - avcodec_default_release_buffer(c, pic); -} - - static int stream_component_open(VideoState *is, int stream_index, Lisp_Media_Stream *ms) { @@ -1079,12 +1077,12 @@ stream_component_open(VideoState *is, int stream_index, Lisp_Media_Stream *ms) enc->error_resilience = FF_ER_CAREFUL; /* error_resilience; */ #endif enc->error_concealment = 3; /* error_concealment; */ + if (1 /* thread_count */ > 1) + enc->thread_count = 1 /* thread_count */; + if (!codec || - avcodec_open(enc, codec) < 0) + avcodec_open2(enc, codec, NULL) < 0) return -1; - if (1 /* thread_count */ > 1) - avcodec_thread_init(enc, 1 /*thread_count*/); - enc->thread_count= 1 /* thread_count */; /* create a substream */ mss = make_media_substream_append(ms); @@ -1124,10 +1122,9 @@ stream_component_open(VideoState *is, int stream_index, Lisp_Media_Stream *ms) packet_queue_init(&is->videoq); is->video_tid = 0 /* SDL_CreateThread(video_thread, is) */; - enc-> get_buffer= my_get_buffer; - enc->release_buffer= my_release_buffer; - + enc->get_buffer2 = my_get_buffer; media_substream_type(mss) = MTYPE_VIDEO; + media_ffmpeg_analyse_video(mss, is->ic, stream_index); break; case AVMEDIA_TYPE_SUBTITLE: @@ -1247,9 +1244,9 @@ enum { static VideoState * stream_open(char *filename, size_t filelen) { - VideoState *is = xnew(VideoState); - AVFormatParameters params, *ap = ¶ms; - int err = 0; + VideoState *is = xnew(VideoState); + AVDictionary *options = NULL; + int err = 0; is->filename = filename; is->filelen = filelen; @@ -1264,7 +1261,7 @@ stream_open(char *filename, size_t filelen) is->av_sync_type = AV_SYNC_AUDIO_MASTER; is->parse_tid = 0; /* SDL_CreateThread(decode_thread, is); */ - memset(ap, 0, sizeof(*ap)); +#if 0 /* we force a pause when starting an RTSP stream */ ap->initial_pause = 1; @@ -1272,8 +1269,9 @@ stream_open(char *filename, size_t filelen) ap->height= 0; /* frame_height; */ ap->time_base= (AVRational){1, 25}; ap->pix_fmt = PIX_FMT_NONE; /* frame_pix_fmt; */ +#endif - err = avformat_open_input(&is->ic, is->filename, is->iformat, NULL /*ap*/); + err = avformat_open_input(&is->ic, is->filename, is->iformat, &options); if (UNLIKELY(err < 0)) { FFMPEG_DEBUG_AVF("Could not open \"%s\" (errno %d)\n", is->filename, err); @@ -1338,11 +1336,7 @@ new_media_ffmpeg_open(Lisp_Media_Stream *ms) } /* FIXME hack, * ffplay maybe should not use url_feof() to test for the end */ -#if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR vs->ic->pb->eof_reached = 0; -#elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR - vs->ic->pb.eof_reached = 0; -#endif } /* now we can begin to play (RTSP stream only) */ @@ -1504,25 +1498,14 @@ new_media_ffmpeg_read(media_substream *mss, void *outbuf, size_t length) if (is->audioq.size > MAX_AUDIOQ_SIZE || is->videoq.size > MAX_VIDEOQ_SIZE || is->subtitleq.size > MAX_SUBTITLEQ_SIZE || -#if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR - url_feof(is->ic->pb) -#elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR - url_feof(&is->ic->pb) -#endif - ) { + avio_feof(is->ic->pb)) { /* wait 10 ms */ usleep(10); continue; } ret = av_read_frame(is->ic, pkt); if (ret < 0) { - if (url_ferror( -#if defined FFMPEG_URL_FOPEN_BIOCTX_STAR_STAR - is->ic->pb -#elif defined FFMPEG_URL_FOPEN_BIOCTX_STAR - &is->ic->pb -#endif - ) == 0) { + if (is->ic->pb->error == 0) { usleep(100); /* wait for user event */ continue; } else @@ -1556,7 +1539,10 @@ new_media_ffmpeg_read(media_substream *mss, void *outbuf, size_t length) avformat_close_input(&is->ic); is->ic = NULL; /* safety */ } + +#if 0 url_set_interrupt_cb(NULL); +#endif if (ret != 0) { #if 0 @@ -1619,12 +1605,12 @@ Lisp_Object media_ffmpeg_available_formats(void) { Lisp_Object formats; - AVInputFormat *avif; + AVInputFormat *avif = NULL; formats = Qnil; av_register_all(); - avif = first_iformat; + avif = av_iformat_next(avif); while (avif) { if (avif->name) { @@ -1632,7 +1618,7 @@ media_ffmpeg_available_formats(void) Fintern(build_string(avif->name), Qnil); formats = Fcons(fmtname, formats); } - avif = avif->next; + avif = av_iformat_next(avif); } return formats;