diff options
author | Johns <johns98@gmx.net> | 2011-12-08 18:58:10 +0100 |
---|---|---|
committer | Johns <johns98@gmx.net> | 2011-12-08 20:45:20 +0100 |
commit | 3f8ff57e30c82500511d40f718f6f80aafd37d20 (patch) | |
tree | f0081a6a90f3c036d16834eec1fe8eb97f988aca /codec.c | |
parent | fc2580dc2aee2a7b86d3ca5428ce2e2e57c060b2 (diff) | |
download | vdr-plugin-softhddevice-3f8ff57e30c82500511d40f718f6f80aafd37d20.tar.gz vdr-plugin-softhddevice-3f8ff57e30c82500511d40f718f6f80aafd37d20.tar.bz2 |
Audio improvement.
Made audio thread cancelable.
Calculate audio PTS.
Disable alsa message to stderr.
Better buffer flush with threaded play.
Prepared audio resample, for unsupported number of audio channels.
Diffstat (limited to 'codec.c')
-rw-r--r-- | codec.c | 94 |
1 files changed, 86 insertions, 8 deletions
@@ -346,7 +346,7 @@ void CodecVideoClose(VideoDecoder * video_decoder) { // FIXME: play buffered data av_freep(&video_decoder->Frame); - if ( video_decoder->VideoCtx ) { + if (video_decoder->VideoCtx) { avcodec_close(video_decoder->VideoCtx); av_freep(&video_decoder->VideoCtx); } @@ -455,8 +455,13 @@ struct _audio_decoder_ /// audio parser to support wired dvb streaks AVCodecParserContext *AudioParser; - int SampleRate; ///< old sample rate - int Channels; ///< old channels + int SampleRate; ///< current sample rate + int Channels; ///< current channels + + int HwSampleRate; ///< hw sample rate + int HwChannels; ///< hw channels + + ReSampleContext *ReSample; ///< audio resampling context }; /** @@ -525,6 +530,10 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name, void CodecAudioClose(AudioDecoder * audio_decoder) { // FIXME: output any buffered data + if (audio_decoder->ReSample) { + audio_resample_close(audio_decoder->ReSample); + audio_decoder->ReSample = NULL; + } if (audio_decoder->AudioParser) { av_parser_close(audio_decoder->AudioParser); audio_decoder->AudioParser = NULL; @@ -549,11 +558,13 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, AVPacket * avpkt) FF_INPUT_BUFFER_PADDING_SIZE] __attribute__ ((aligned(16))); AVCodecContext *audio_ctx; int index; - AVPacket spkt[1]; if (!audio_decoder->AudioParser) { Fatal(_("codec: internal error parser freeded while running\n")); } +#define spkt avpkt +#if 0 + AVPacket spkt[1]; if (av_new_packet(spkt, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE)) { Error(_("codec: out of memory\n")); @@ -561,6 +572,9 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, AVPacket * avpkt) } memcpy(spkt->data, avpkt->data, avpkt->size); memset(spkt->data + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + spkt->pts = avpkt->pts; +#endif + audio_ctx = audio_decoder->AudioCtx; index = 0; while (avpkt->size > index) { @@ -571,11 +585,13 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, AVPacket * avpkt) av_init_packet(dpkt); n = av_parser_parse2(audio_decoder->AudioParser, audio_ctx, &dpkt->data, &dpkt->size, spkt->data + index, avpkt->size - index, - AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE); + !index ? (uint64_t) spkt->pts : AV_NOPTS_VALUE, AV_NOPTS_VALUE, + -1); if (dpkt->size) { int buf_sz; + dpkt->pts = audio_decoder->AudioParser->pts; buf_sz = sizeof(buf); l = avcodec_decode_audio3(audio_ctx, buf, &buf_sz, dpkt); if (l < 0) { // no audio frame could be decompressed @@ -589,17 +605,62 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, AVPacket * avpkt) avcodec_decode_audio4(audio_ctx, frame, &got_frame, dpkt); #else #endif + // Update audio clock + if ((uint64_t) dpkt->pts != AV_NOPTS_VALUE) { + AudioSetClock(dpkt->pts); + } // FIXME: must first play remainings bytes, than change and play new. if (audio_decoder->SampleRate != audio_ctx->sample_rate || audio_decoder->Channels != audio_ctx->channels) { + int err; - // FIXME: channels not support? - AudioSetup(audio_ctx->sample_rate, audio_ctx->channels); + if (audio_decoder->ReSample) { + audio_resample_close(audio_decoder->ReSample); + audio_decoder->ReSample = NULL; + } audio_decoder->SampleRate = audio_ctx->sample_rate; + audio_decoder->HwSampleRate = audio_ctx->sample_rate; audio_decoder->Channels = audio_ctx->channels; + audio_decoder->HwChannels = audio_ctx->channels; + + // channels not support? + if ((err = + AudioSetup(&audio_decoder->HwSampleRate, + &audio_decoder->HwChannels))) { + Debug(3, "codec/audio: resample %d -> %d\n", + audio_ctx->channels, audio_decoder->HwChannels); + + if (err == 1) { + audio_decoder->ReSample = + av_audio_resample_init(audio_decoder->HwChannels, + audio_ctx->channels, audio_decoder->HwSampleRate, + audio_ctx->sample_rate, audio_ctx->sample_fmt, + audio_ctx->sample_fmt, 16, 10, 0, 0.8); + } else { + // FIXME: handle errors + audio_decoder->HwChannels = 0; + audio_decoder->HwSampleRate = 0; + } + } + } + + if (audio_decoder->HwSampleRate && audio_decoder->HwChannels) { + // need to resample audio + if (audio_decoder->ReSample) { + int16_t outbuf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 + + FF_INPUT_BUFFER_PADDING_SIZE] + __attribute__ ((aligned(16))); + int outlen; + + outlen = + audio_resample(audio_decoder->ReSample, outbuf, buf, + buf_sz); + AudioEnqueue(outbuf, outlen); + } else { + AudioEnqueue(buf, buf_sz); + } } - AudioEnqueue(buf, buf_sz); if (dpkt->size > l) { Error(_("codec: error more than one frame data\n")); @@ -608,7 +669,10 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, AVPacket * avpkt) index += n; } + +#if 0 av_destruct_packet(spkt); +#endif } //---------------------------------------------------------------------------- @@ -616,10 +680,24 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, AVPacket * avpkt) //---------------------------------------------------------------------------- /** +** Empty log callback +*/ +static void CodecNoopCallback( __attribute__ ((unused)) + void *ptr, __attribute__ ((unused)) + int level, __attribute__ ((unused)) + const char *fmt, __attribute__ ((unused)) va_list vl) +{ +} + +/** ** Codec init */ void CodecInit(void) { +#ifndef DEBUG + // display ffmpeg error messages + av_log_set_callback(CodecNoopCallback); +#endif avcodec_register_all(); // register all formats and codecs } |