diff --git a/configure.ac b/configure.ac index d490a48..697556d 100644 --- a/configure.ac +++ b/configure.ac @@ -30,7 +30,6 @@ if test x$BOXTYPE = xgeneric; then PKG_CHECK_MODULES([AVCODEC], [libavcodec >= 54.28.0]) # don't know which version is exactly needed here... PKG_CHECK_MODULES([SWSCALE], [libswscale]) - PKG_CHECK_MODULES([SWRESAMPLE], [libswresample]) else # openmaxil are the broadcom userspace libs # my yocto (openembedded) layer has an openmaxil package built from userland git. @@ -46,6 +45,7 @@ if test x$BOXTYPE = xgeneric; then PKG_CHECK_MODULES([AVFORMAT], [libavformat]) PKG_CHECK_MODULES([AVCODEC], [libavcodec]) fi + PKG_CHECK_MODULES([SWRESAMPLE], [libswresample]) # don't know which version is exactly needed here... PKG_CHECK_MODULES([AVUTIL], [libavutil]) fi diff --git a/raspi/Makefile.am b/raspi/Makefile.am index cf9d148..3cab3e5 100644 --- a/raspi/Makefile.am +++ b/raspi/Makefile.am @@ -13,6 +13,7 @@ AM_LDFLAGS = \ @AVFORMAT_LIBS@ \ @AVUTIL_LIBS@ \ @AVCODEC_LIBS@ \ + @SWRESAMPLE_LIBS@ \ @OMX_LIBS@ \ -lOpenThreads diff --git a/raspi/avdec.cpp b/raspi/avdec.cpp index 0090966..85fc599 100644 --- a/raspi/avdec.cpp +++ b/raspi/avdec.cpp @@ -33,6 +33,7 @@ extern "C" { #include #include #include +#include //#include #include "codec.h" #include "avcodec_omx.h" @@ -329,6 +330,13 @@ void aDec::run() AVCodecContext *c = NULL; AVInputFormat *inp; AVFrame *frame; + /* resample / sample format conversion */ + SwrContext *swr = NULL; + uint8_t *obuf = NULL; + int obuf_sz = 0; /* in samples */ + int obuf_sz_max = 0; + int o_ch = 2, o_sr = 48000; /* output channels and sample rate */ + uint8_t *inbuf; AVPacket avpkt; char tmp[128] = "unknown"; @@ -375,6 +383,10 @@ void aDec::run() lt_info("aDec: Codec for codec_id 0x%08x not found\n", c->codec_id); goto out; } + /* now using libswresample anyway + if (c->sample_fmt == AV_SAMPLE_FMT_S16P) + c->request_sample_fmt = AV_SAMPLE_FMT_S16; + */ if (avcodec_open2(c, codec, NULL) < 0) { lt_info("aDec: avcodec_open2() failed\n"); goto out; @@ -387,6 +399,15 @@ void aDec::run() /* output sample rate, channels, layout could be set here if necessary */ avcodec_string(tmp, sizeof(tmp), c, 0); lt_info("aDec: decoding %s\n", tmp); + swr = swr_alloc_set_opts(swr, + AV_CH_LAYOUT_STEREO, 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 (dec_running) { int gotframe = 0; if (av_read_frame(avfc, &avpkt) < 0) { @@ -398,19 +419,36 @@ void aDec::run() av_free_packet(&avpkt); continue; } + int len = avcodec_decode_audio4(c, frame, &gotframe, &avpkt); if (gotframe && dec_running) { - curr_pts = (avpkt.pts); + 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); apts = curr_pts; lt_debug("aDec: pts 0x%" PRIx64 " %3f\n", curr_pts, curr_pts/90000.0); - int data_size = av_samples_get_buffer_size(NULL, c->channels, - frame->nb_samples, c->sample_fmt, 1); + int data_size = av_samples_get_buffer_size(&out_linesize, o_ch, + obuf_sz, AV_SAMPLE_FMT_S16, 1); packet = (packet_t *)malloc(sizeof(*packet)); packet->PTS = av_rescale_q(avpkt.pts, avfc->streams[0]->time_base, omx_timebase); packet->DTS = -1; packet->packetlength = data_size; packet->packet = (uint8_t *)malloc(data_size); - memcpy(packet->packet, frame->data[0], data_size); + memcpy(packet->packet, obuf, data_size); packet->buf = packet->packet; /* This is what is free()ed */ codec_queue_add_item(&codecs.acodec, packet, MSG_PACKET); } @@ -419,6 +457,8 @@ void aDec::run() av_free_packet(&avpkt); } lt_info("aDec: decoder loop exited\n"); + swr_free(&swr); + out3: #if LIBAVCODEC_VERSION_INT >= (54 << 16 | 28 << 8) avcodec_free_frame(&frame); #else