From e5e05ffa095fb0714507a85f3f64dd05493a141f Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 1 Jun 2013 12:25:52 +0200 Subject: [PATCH 1/6] fix library declarations for libtool --- Makefile.am | 17 +---------------- generic-pc/Makefile.am | 9 +++++++++ libspark/Makefile.am | 2 +- libtriple/Makefile.am | 2 ++ 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/Makefile.am b/Makefile.am index 9a1589b..d5cd6a3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,14 +9,7 @@ libstb_hal_la_LIBADD = \ common/libcommon.la libstb_hal_test_SOURCES = libtest.cpp -libstb_hal_test_LDADD = \ - libstb-hal.la \ - -lpthread - -if BOXTYPE_TRIPLE -libstb_hal_test_LDADD += \ - @DIRECTFB_LIBS@ -endif +libstb_hal_test_LDADD = libstb-hal.la # there has to be a better way to do this... if BOXTYPE_TRIPLE @@ -33,14 +26,6 @@ if BOXTYPE_GENERIC SUBDIRS += generic-pc libstb_hal_la_LIBADD += \ generic-pc/libgeneric.la - -libstb_hal_test_LDADD += \ - -lglut -lGL -lGLU -lGLEW -lao \ - -lOpenThreads \ - @AVFORMAT_LIBS@ \ - @AVUTIL_LIBS@ \ - @AVCODEC_LIBS@ \ - @SWSCALE_LIBS@ endif if BOXTYPE_SPARK SUBDIRS += libspark libeplayer3 diff --git a/generic-pc/Makefile.am b/generic-pc/Makefile.am index a5be1e2..130e419 100644 --- a/generic-pc/Makefile.am +++ b/generic-pc/Makefile.am @@ -6,6 +6,15 @@ noinst_LTLIBRARIES = libgeneric.la AM_CPPFLAGS = -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing +AM_LDFLAGS = \ + -lglut -lGL -lGLU -lGLEW -lao \ + -lOpenThreads \ + @AVFORMAT_LIBS@ \ + @AVUTIL_LIBS@ \ + @AVCODEC_LIBS@ \ + @SWRESAMPLE_LIBS@ \ + @SWSCALE_LIBS@ + libgeneric_la_SOURCES = \ hardware_caps.c \ dmx.cpp \ diff --git a/libspark/Makefile.am b/libspark/Makefile.am index ffb7195..39afbd1 100644 --- a/libspark/Makefile.am +++ b/libspark/Makefile.am @@ -5,7 +5,7 @@ INCLUDES = \ noinst_LTLIBRARIES = libspark.la AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing -AM_LDFLAGS = -lpthread +AM_LDFLAGS = -lpthread -lass libspark_la_SOURCES = \ irmp.c \ diff --git a/libtriple/Makefile.am b/libtriple/Makefile.am index 697be37..1bad773 100644 --- a/libtriple/Makefile.am +++ b/libtriple/Makefile.am @@ -5,6 +5,8 @@ INCLUDES = \ noinst_LTLIBRARIES = libtriple.la AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing +AM_LDFLAGS = \ + @DIRECTFB_LIBS@ libtriple_la_SOURCES = \ hardware_caps.c \ From f4f72f34b9a60a0f9a5f11885b483e036d1da67c Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 1 Jun 2013 13:43:51 +0200 Subject: [PATCH 2/6] generic-pc: add audio sample conversion ffmpeg audiodecoders after version 1.1 deliver audio samples in planar formats by default instead of packed as before. Additionally, the AC3 decoder delivers now in planar float. Use libswresample for sample format conversion, this will work with old (where it hopefully does nothing) and new ffmpeg versions. Later on, also sample rate and channel layout conversion could be implemented if desired. Tested with ffmpeg versions 1.0.6 and 1.2.1. --- configure.ac | 1 + generic-pc/audio.cpp | 56 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 163d9ea..88dbf02 100644 --- a/configure.ac +++ b/configure.ac @@ -29,6 +29,7 @@ if test x$BOXTYPE = xgeneric; then # don't know which version is exactly needed here... PKG_CHECK_MODULES([AVUTIL], [libavutil]) PKG_CHECK_MODULES([SWSCALE], [libswscale]) + PKG_CHECK_MODULES([SWRESAMPLE], [libswresample]) fi AC_OUTPUT([ Makefile diff --git a/generic-pc/audio.cpp b/generic-pc/audio.cpp index 99effcd..fc1cd2f 100644 --- a/generic-pc/audio.cpp +++ b/generic-pc/audio.cpp @@ -16,7 +16,7 @@ * * cAudio implementation with decoder. * uses libao for output - * ffmpeg for demuxing / decoding + * ffmpeg for demuxing / decoding / format conversion */ #include @@ -33,6 +33,9 @@ extern "C" { #include +#include +#include +#include #include } /* ffmpeg buf 2k */ @@ -279,6 +282,13 @@ void cAudio::run() ao_info *ai; // ao_device *adevice; // ao_sample_format sformat; + /* resample */ + SwrContext *swr = NULL; + uint8_t *obuf = NULL; + int obuf_sz = 0; /* in samples */ + int obuf_sz_max = 0; + int o_ch, o_sr; /* output channels and sample rate */ + uint64_t o_layout; /* output channels layout */ curr_pts = 0; av_init_packet(&avpkt); @@ -324,13 +334,17 @@ void cAudio::run() lt_info("%s: avcodec_alloc_frame failed\n", __func__); goto out2; } - if (sformat.channels != c->channels || sformat.rate != c->sample_rate || + /* output sample rate, channels, layout could be set here if necessary */ + o_ch = c->channels; /* 2 */ + o_sr = c->sample_rate; /* 48000 */ + o_layout = c->channel_layout; /* AV_CH_LAYOUT_STEREO */ + if (sformat.channels != o_ch || sformat.rate != o_sr || sformat.byte_format != AO_FMT_NATIVE || sformat.bits != 16 || adevice == NULL) { driver = ao_default_driver_id(); sformat.bits = 16; - sformat.channels = c->channels; - sformat.rate = c->sample_rate; + sformat.channels = o_ch; + sformat.rate = o_sr; sformat.byte_format = AO_FMT_NATIVE; sformat.matrix = 0; if (adevice) @@ -338,7 +352,7 @@ void cAudio::run() adevice = ao_open_live(driver, &sformat, NULL); ai = ao_driver_info(driver); lt_info("%s: changed params ch %d srate %d bits %d adevice %p\n", - __func__, c->channels, c->sample_rate, 16, adevice);; + __func__, o_ch, o_sr, 16, adevice);; lt_info("libao driver: %d name '%s' short '%s' author '%s'\n", driver, ai->name, ai->short_name, ai->author); } @@ -350,19 +364,49 @@ void cAudio::run() #endif lt_info("codec params: sample_fmt %d sample_rate %d channels %d\n", c->sample_fmt, c->sample_rate, c->channels); + swr = swr_alloc_set_opts(swr, + o_layout, AV_SAMPLE_FMT_S16, o_sr, /* output */ + c->channel_layout, c->sample_fmt, c->sample_rate, /* input */ + 0, NULL); + if (! swr) { + lt_info("could not alloc resample context\n"); + goto out3; + } + swr_init(swr); while (thread_started) { int gotframe = 0; if (av_read_frame(avfc, &avpkt) < 0) break; avcodec_decode_audio4(c, frame, &gotframe, &avpkt); if (gotframe && thread_started) { + int out_linesize; + obuf_sz = av_rescale_rnd(swr_get_delay(swr, c->sample_rate) + + frame->nb_samples, o_sr, c->sample_rate, AV_ROUND_UP); + if (obuf_sz > obuf_sz_max) { + lt_info("obuf_sz: %d old: %d\n", obuf_sz, obuf_sz_max); + av_free(obuf); + if (av_samples_alloc(&obuf, &out_linesize, o_ch, + frame->nb_samples, AV_SAMPLE_FMT_S16, 1) < 0) { + lt_info("av_samples_alloc failed\n"); + av_free_packet(&avpkt); + break; /* while (thread_started) */ + } + obuf_sz_max = obuf_sz; + } + obuf_sz = swr_convert(swr, &obuf, obuf_sz, + (const uint8_t **)frame->extended_data, frame->nb_samples); curr_pts = av_frame_get_best_effort_timestamp(frame); lt_debug("%s: pts 0x%" PRIx64 " %3f\n", __func__, curr_pts, curr_pts/90000.0); - ao_play(adevice, (char*)frame->extended_data[0], frame->linesize[0]); + int o_buf_sz = av_samples_get_buffer_size(&out_linesize, o_ch, + obuf_sz, AV_SAMPLE_FMT_S16, 1); + ao_play(adevice, (char *)obuf, o_buf_sz); } av_free_packet(&avpkt); } // ao_close(adevice); /* can take long :-( */ + av_free(obuf); + swr_free(&swr); + out3: avcodec_free_frame(&frame); out2: avcodec_close(c); From 2efe616a239bd2b63c81b0cec1e79e187dba7833 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 1 Jun 2013 15:21:43 +0200 Subject: [PATCH 3/6] generic-pc: implement cAudio::getAudioInfo() --- generic-pc/audio.cpp | 51 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/generic-pc/audio.cpp b/generic-pc/audio.cpp index fc1cd2f..4c61c54 100644 --- a/generic-pc/audio.cpp +++ b/generic-pc/audio.cpp @@ -55,6 +55,8 @@ static cAudio *gThiz = NULL; static ao_device *adevice = NULL; static ao_sample_format sformat; +static AVCodecContext *c= NULL; + cAudio::cAudio(void *, void *, void *) { thread_started = false; @@ -194,12 +196,51 @@ int cAudio::StopClip() void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode) { - lt_debug("%s\n", __func__); type = 0; - layer = 0; + layer = 0; /* not used */ freq = 0; - bitrate = 0; - mode = 0; + bitrate = 0; /* not used, but easy to get :-) */ + mode = 0; /* default: stereo */ + if (c) { + type = (c->codec_id != AV_CODEC_ID_MP2); /* only mpeg / not mpeg is indicated */ + freq = c->sample_rate; + bitrate = c->bit_rate; + if (c->channels == 1) + mode = 3; /* for AV_CODEC_ID_MP2, only stereo / mono is detected for now */ + if (c->codec_id != AV_CODEC_ID_MP2) { + switch (c->channel_layout) { + case AV_CH_LAYOUT_MONO: + mode = 1; // "C" + break; + case AV_CH_LAYOUT_STEREO: + mode = 2; // "L/R" + break; + case AV_CH_LAYOUT_2_1: + case AV_CH_LAYOUT_SURROUND: + mode = 3; // "L/C/R" + break; + case AV_CH_LAYOUT_2POINT1: + mode = 4; // "L/R/S" + break; + case AV_CH_LAYOUT_3POINT1: + mode = 5; // "L/C/R/S" + break; + case AV_CH_LAYOUT_2_2: + case AV_CH_LAYOUT_QUAD: + mode = 6; // "L/R/SL/SR" + break; + case AV_CH_LAYOUT_5POINT0: + case AV_CH_LAYOUT_5POINT1: + mode = 7; // "L/C/R/SL/SR" + break; + default: + lt_info("%s: unknown ch_layout 0x%" PRIx64 "\n", + __func__, c->channel_layout); + } + } + } + lt_debug("%s t: %d l: %d f: %d b: %d m: %d codec_id: %x\n", + __func__, type, layer, freq, bitrate, mode, c->codec_id); }; void cAudio::SetSRS(int /*iq_enable*/, int /*nmgr_enable*/, int /*iq_mode*/, int /*iq_level*/) @@ -271,7 +312,6 @@ void cAudio::run() av_register_all(); AVCodec *codec; - AVCodecContext *c= NULL; AVFormatContext *avfc = NULL; AVInputFormat *inp; AVFrame *frame; @@ -410,6 +450,7 @@ void cAudio::run() avcodec_free_frame(&frame); out2: avcodec_close(c); + c = NULL; out: avformat_close_input(&avfc); av_free(pIOCtx->buffer); From 619751eaf062862a88b6ad17799c41fb41a96260 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 1 Jun 2013 15:39:19 +0200 Subject: [PATCH 4/6] generic-pc: silence decoder threads output --- generic-pc/audio.cpp | 8 ++++---- generic-pc/video.cpp | 9 ++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/generic-pc/audio.cpp b/generic-pc/audio.cpp index 4c61c54..ad91df5 100644 --- a/generic-pc/audio.cpp +++ b/generic-pc/audio.cpp @@ -102,22 +102,22 @@ int cAudio::setVolume(unsigned int left, unsigned int right) int cAudio::Start(void) { - lt_info("%s >\n", __func__); + lt_debug("%s >\n", __func__); if (! HAL_nodec) OpenThreads::Thread::start(); - lt_info("%s <\n", __func__); + lt_debug("%s <\n", __func__); return 0; } int cAudio::Stop(void) { - lt_info("%s >\n", __func__); + lt_debug("%s >\n", __func__); if (thread_started) { thread_started = false; OpenThreads::Thread::join(); } - lt_info("%s <\n", __func__); + lt_debug("%s <\n", __func__); return 0; } diff --git a/generic-pc/video.cpp b/generic-pc/video.cpp index 5c4616f..2164be1 100644 --- a/generic-pc/video.cpp +++ b/generic-pc/video.cpp @@ -139,21 +139,21 @@ int cVideo::setCroppingMode(int) int cVideo::Start(void *, unsigned short, unsigned short, void *) { - lt_info("%s running %d >\n", __func__, thread_running); + lt_debug("%s running %d >\n", __func__, thread_running); if (!thread_running && !HAL_nodec) OpenThreads::Thread::start(); - lt_info("%s running %d <\n", __func__, thread_running); + lt_debug("%s running %d <\n", __func__, thread_running); return 0; } int cVideo::Stop(bool) { - lt_info("%s running %d >\n", __func__, thread_running); + lt_debug("%s running %d >\n", __func__, thread_running); if (thread_running) { thread_running = false; OpenThreads::Thread::join(); } - lt_info("%s running %d <\n", __func__, thread_running); + lt_debug("%s running %d <\n", __func__, thread_running); return 0; } @@ -438,7 +438,6 @@ void cVideo::run(void) if (! thread_running) goto out; } - lt_info("%s: nb_streams %d\n", __func__, avfc->nb_streams); if (avfc->streams[0]->codec->codec_type != AVMEDIA_TYPE_VIDEO) lt_info("%s: no video codec? 0x%x\n", __func__, avfc->streams[0]->codec->codec_type); From 94830cf33ff1ac3fd385935761a64be7165a4f85 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 1 Jun 2013 15:41:32 +0200 Subject: [PATCH 5/6] generic-pc: improve decoder info messages --- generic-pc/audio.cpp | 8 +++++--- generic-pc/video.cpp | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/generic-pc/audio.cpp b/generic-pc/audio.cpp index ad91df5..8d6f317 100644 --- a/generic-pc/audio.cpp +++ b/generic-pc/audio.cpp @@ -329,6 +329,7 @@ void cAudio::run() int obuf_sz_max = 0; int o_ch, o_sr; /* output channels and sample rate */ uint64_t o_layout; /* output channels layout */ + char tmp[64] = "unknown"; curr_pts = 0; av_init_packet(&avpkt); @@ -362,7 +363,7 @@ void cAudio::run() c = avfc->streams[0]->codec; codec = avcodec_find_decoder(c->codec_id); if (!codec) { - lt_info("%s: Codec not found\n", __func__); + lt_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(c->codec_id)); goto out; } if (avcodec_open2(c, codec, NULL) < 0) { @@ -402,8 +403,9 @@ void cAudio::run() fprintf(stderr, " %s", ai->options[i]); fprintf(stderr, "\n"); #endif - lt_info("codec params: sample_fmt %d sample_rate %d channels %d\n", - c->sample_fmt, c->sample_rate, c->channels); + av_get_sample_fmt_string(tmp, sizeof(tmp), c->sample_fmt); + lt_info("decoding %s, sample_fmt %d (%s) sample_rate %d channels %d\n", + avcodec_get_name(c->codec_id), c->sample_fmt, tmp, c->sample_rate, c->channels); swr = swr_alloc_set_opts(swr, o_layout, AV_SAMPLE_FMT_S16, o_sr, /* output */ c->channel_layout, c->sample_fmt, c->sample_rate, /* input */ diff --git a/generic-pc/video.cpp b/generic-pc/video.cpp index 2164be1..92ee802 100644 --- a/generic-pc/video.cpp +++ b/generic-pc/video.cpp @@ -445,7 +445,7 @@ void cVideo::run(void) c = avfc->streams[0]->codec; codec = avcodec_find_decoder(c->codec_id); if (!codec) { - lt_info("%s: Codec not found\n", __func__); + lt_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(c->codec_id)); goto out; } if (avcodec_open2(c, codec, NULL) < 0) { @@ -458,6 +458,7 @@ void cVideo::run(void) lt_info("%s: Could not allocate video frame\n", __func__); goto out2; } + lt_info("decoding %s\n", avcodec_get_name(c->codec_id)); while (thread_running) { if (av_read_frame(avfc, &avpkt) < 0) { if (warn_r - time(NULL) > 4) { From 437a7d1b5191c77094bde42c69eb5e8b0648ed02 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 1 Jun 2013 15:58:47 +0200 Subject: [PATCH 6/6] generic-pc: help finding missing blit() calls --- generic-pc/init.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/generic-pc/init.cpp b/generic-pc/init.cpp index 5fadc88..c26048b 100644 --- a/generic-pc/init.cpp +++ b/generic-pc/init.cpp @@ -40,6 +40,8 @@ void init_td_api() * valgrind-check other parts... export HAL_NOAVDEC=1 */ if (getenv("HAL_NOAVDEC")) HAL_nodec = true; + /* hack, this triggers that the simple_display thread does not blit() once per second... */ + setenv("SPARK_NOBLIT", "1", 1); initialized = true; }