mirror of
				https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
				synced 2023-10-10 17:16:51 +00:00 
			
		
		
		
	Experimental ac3 audio drift correction support.
This commit is contained in:
		@@ -1,6 +1,7 @@
 | 
			
		||||
User johns
 | 
			
		||||
Date:
 | 
			
		||||
 | 
			
		||||
    Experimental ac3 audio drift correction support.
 | 
			
		||||
    Removes LPCM detection from TS parser.
 | 
			
		||||
    Rewrote video/audio start code.
 | 
			
		||||
    Add support for attach/detach plugin.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										72
									
								
								codec.c
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								codec.c
									
									
									
									
									
								
							@@ -352,7 +352,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
 | 
			
		||||
{
 | 
			
		||||
    AVCodec *video_codec;
 | 
			
		||||
 | 
			
		||||
    Debug(3, "codec: using codec %s or ID %#04x\n", name, codec_id);
 | 
			
		||||
    Debug(3, "codec: using video codec %s or ID %#06x\n", name, codec_id);
 | 
			
		||||
 | 
			
		||||
    if (decoder->VideoCtx) {
 | 
			
		||||
	Error(_("codec: missing close\n"));
 | 
			
		||||
@@ -377,7 +377,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
 | 
			
		||||
    if (name && (video_codec = avcodec_find_decoder_by_name(name))) {
 | 
			
		||||
	Debug(3, "codec: vdpau decoder found\n");
 | 
			
		||||
    } else if (!(video_codec = avcodec_find_decoder(codec_id))) {
 | 
			
		||||
	Fatal(_("codec: codec ID %#04x not found\n"), codec_id);
 | 
			
		||||
	Fatal(_("codec: codec ID %#06x not found\n"), codec_id);
 | 
			
		||||
	// FIXME: none fatal
 | 
			
		||||
    }
 | 
			
		||||
    decoder->VideoCodec = video_codec;
 | 
			
		||||
@@ -615,6 +615,7 @@ struct _audio_decoder_
 | 
			
		||||
 | 
			
		||||
    int Drift;				///< accumulated audio drift
 | 
			
		||||
    int DriftCorr;			///< audio drift correction value
 | 
			
		||||
    int DriftFrac;			///< audio drift fraction for ac3
 | 
			
		||||
 | 
			
		||||
    struct AVResampleContext *AvResample;	///< second audio resample context
 | 
			
		||||
#define MAX_CHANNELS 8			///< max number of channels supported
 | 
			
		||||
@@ -675,10 +676,12 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
 | 
			
		||||
{
 | 
			
		||||
    AVCodec *audio_codec;
 | 
			
		||||
 | 
			
		||||
    Debug(3, "codec: using audio codec %s or ID %#06x\n", name, codec_id);
 | 
			
		||||
 | 
			
		||||
    if (name && (audio_codec = avcodec_find_decoder_by_name(name))) {
 | 
			
		||||
	Debug(3, "codec: audio decoder '%s' found\n", name);
 | 
			
		||||
    } else if (!(audio_codec = avcodec_find_decoder(codec_id))) {
 | 
			
		||||
	Fatal(_("codec: codec ID %#04x not found\n"), codec_id);
 | 
			
		||||
	Fatal(_("codec: codec ID %#06x not found\n"), codec_id);
 | 
			
		||||
	// FIXME: errors aren't fatal
 | 
			
		||||
    }
 | 
			
		||||
    audio_decoder->AudioCodec = audio_codec;
 | 
			
		||||
@@ -846,6 +849,7 @@ static void CodecReorderAudioFrame(int16_t * buf, int size, int channels)
 | 
			
		||||
**	Set/update audio pts clock.
 | 
			
		||||
**
 | 
			
		||||
**	@param audio_decoder	audio decoder data
 | 
			
		||||
**	@param pts		presentation timestamp
 | 
			
		||||
*/
 | 
			
		||||
static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
 | 
			
		||||
{
 | 
			
		||||
@@ -868,6 +872,7 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
 | 
			
		||||
	audio_decoder->LastPTS = pts;
 | 
			
		||||
	audio_decoder->LastDelay = delay;
 | 
			
		||||
	audio_decoder->Drift = 0;
 | 
			
		||||
	audio_decoder->DriftFrac = 0;
 | 
			
		||||
	Debug(3, "codec/audio: inital delay %zd ms\n", delay / 90);
 | 
			
		||||
	return;
 | 
			
		||||
    }
 | 
			
		||||
@@ -885,34 +890,35 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
 | 
			
		||||
	(tim_diff * 90) / (1000 * 1000) - pts_diff + delay -
 | 
			
		||||
	audio_decoder->LastDelay;
 | 
			
		||||
 | 
			
		||||
    // adjust rounding error
 | 
			
		||||
    nowtime.tv_nsec -= nowtime.tv_nsec % (1000 * 1000 / 90);
 | 
			
		||||
    audio_decoder->LastTime = nowtime;
 | 
			
		||||
    audio_decoder->LastPTS = pts;
 | 
			
		||||
    audio_decoder->LastDelay = delay;
 | 
			
		||||
 | 
			
		||||
    if (1) {
 | 
			
		||||
    if (0) {
 | 
			
		||||
	Debug(3, "codec/audio: interval P:%5zdms T:%5zdms D:%4zdms %f %d\n",
 | 
			
		||||
	    pts_diff / 90, tim_diff / (1000 * 1000), delay / 90, drift / 90.0,
 | 
			
		||||
	    audio_decoder->DriftCorr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (abs(drift) > 5 * 90) {
 | 
			
		||||
    // underruns and av_resample have the same time :(((
 | 
			
		||||
    if (abs(drift) > 10 * 90) {
 | 
			
		||||
	// drift too big, pts changed?
 | 
			
		||||
	Debug(3, "codec/audio: drift(%5d) %3dms reset\n",
 | 
			
		||||
	    audio_decoder->DriftCorr, drift);
 | 
			
		||||
	Debug(3, "codec/audio: drift(%6d) %3dms reset\n",
 | 
			
		||||
	    audio_decoder->DriftCorr, drift / 90);
 | 
			
		||||
	audio_decoder->LastDelay = 0;
 | 
			
		||||
	return;
 | 
			
		||||
    }
 | 
			
		||||
    } else {
 | 
			
		||||
 | 
			
		||||
	drift += audio_decoder->Drift;
 | 
			
		||||
	audio_decoder->Drift = drift;
 | 
			
		||||
	corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
 | 
			
		||||
#ifdef USE_PASSTHROUGH
 | 
			
		||||
#if defined(USE_PASSTHROUGH) && !defined(USE_AC3_DRIFT_CORRECTION)
 | 
			
		||||
	// SPDIF/HDMI passthrough
 | 
			
		||||
	if (!CodecPassthroughAC3
 | 
			
		||||
	    || audio_decoder->AudioCtx->codec_id != CODEC_ID_AC3)
 | 
			
		||||
#endif
 | 
			
		||||
	{
 | 
			
		||||
	audio_decoder->DriftCorr -= corr;
 | 
			
		||||
	    audio_decoder->DriftCorr = -corr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (audio_decoder->DriftCorr < -20000) {	// limit correction
 | 
			
		||||
@@ -920,11 +926,16 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
 | 
			
		||||
	} else if (audio_decoder->DriftCorr > 20000) {
 | 
			
		||||
	    audio_decoder->DriftCorr = 20000;
 | 
			
		||||
	}
 | 
			
		||||
    if (audio_decoder->AvResample && audio_decoder->DriftCorr) {
 | 
			
		||||
	av_resample_compensate(audio_decoder->AvResample,
 | 
			
		||||
	    audio_decoder->DriftCorr / 10, 10 * audio_decoder->HwSampleRate);
 | 
			
		||||
    }
 | 
			
		||||
    printf("codec/audio: drift(%5d) %8dus %4d\n", audio_decoder->DriftCorr,
 | 
			
		||||
    // FIXME: this works with libav 0.8, and only with >10ms with ffmpeg 0.10
 | 
			
		||||
    if (audio_decoder->AvResample && audio_decoder->DriftCorr) {
 | 
			
		||||
	int distance;
 | 
			
		||||
 | 
			
		||||
	distance = (pts_diff * audio_decoder->HwSampleRate) / (90 * 1000);
 | 
			
		||||
	av_resample_compensate(audio_decoder->AvResample,
 | 
			
		||||
	    audio_decoder->DriftCorr / 10, distance);
 | 
			
		||||
    }
 | 
			
		||||
    Debug(3, "codec/audio: drift(%6d) %8dus %5d\n", audio_decoder->DriftCorr,
 | 
			
		||||
	drift * 1000 / 90, corr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -996,7 +1007,11 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    // prepare audio drift resample
 | 
			
		||||
#ifdef USE_AUDIO_DRIFT_CORRECTION
 | 
			
		||||
    if (!isAC3) {
 | 
			
		||||
	if (audio_decoder->AvResample) {
 | 
			
		||||
	    Error(_("codec/audio: overwrite resample\n"));
 | 
			
		||||
	}
 | 
			
		||||
	audio_decoder->AvResample =
 | 
			
		||||
	    av_resample_init(audio_decoder->HwSampleRate,
 | 
			
		||||
	    audio_decoder->HwSampleRate, 16, 10, 0, 0.8);
 | 
			
		||||
@@ -1005,11 +1020,13 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
 | 
			
		||||
	} else {
 | 
			
		||||
	    // reset drift to some default value
 | 
			
		||||
	    audio_decoder->DriftCorr /= 2;
 | 
			
		||||
	    audio_decoder->DriftFrac = 0;
 | 
			
		||||
	    av_resample_compensate(audio_decoder->AvResample,
 | 
			
		||||
		audio_decoder->DriftCorr / 10,
 | 
			
		||||
		10 * audio_decoder->HwSampleRate);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -1063,7 +1080,6 @@ void CodecAudioEnqueue(AudioDecoder * audio_decoder, int16_t * data, int count)
 | 
			
		||||
	    n = av_resample(audio_decoder->AvResample, buftmp[ch],
 | 
			
		||||
		audio_decoder->Buffer[ch], &consumed, bytes_n / 2,
 | 
			
		||||
		sizeof(buftmp[ch]) / 2, ch == audio_decoder->HwChannels - 1);
 | 
			
		||||
	    //printf("remain%d: %d = %d/%d\n", ch, n, consumed, bytes_n /2);
 | 
			
		||||
	    // fixme remaining channels
 | 
			
		||||
	    if (bytes_n - consumed * 2 > audio_decoder->RemainSize) {
 | 
			
		||||
		audio_decoder->RemainSize = bytes_n - consumed * 2;
 | 
			
		||||
@@ -1178,6 +1194,27 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
 | 
			
		||||
		// build SPDIF header and append A52 audio to it
 | 
			
		||||
		// avpkt is the original data
 | 
			
		||||
		buf_sz = 6144;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_AC3_DRIFT_CORRECTION
 | 
			
		||||
		if (1) {
 | 
			
		||||
		    int x;
 | 
			
		||||
 | 
			
		||||
		    x = (audio_decoder->DriftFrac +
 | 
			
		||||
			(audio_decoder->DriftCorr * buf_sz)) / (10 *
 | 
			
		||||
			audio_decoder->HwSampleRate * 100);
 | 
			
		||||
		    audio_decoder->DriftFrac =
 | 
			
		||||
			(audio_decoder->DriftFrac +
 | 
			
		||||
			(audio_decoder->DriftCorr * buf_sz)) % (10 *
 | 
			
		||||
			audio_decoder->HwSampleRate * 100);
 | 
			
		||||
		    x *= audio_decoder->HwChannels * 4;
 | 
			
		||||
		    if (x < -64) {	// limit correction
 | 
			
		||||
			x = -64;
 | 
			
		||||
		    } else if (x > 64) {
 | 
			
		||||
			x = 64;
 | 
			
		||||
		    }
 | 
			
		||||
		    buf_sz += x;
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
		if (buf_sz < avpkt->size + 8) {
 | 
			
		||||
		    Error(_
 | 
			
		||||
			("codec/audio: decoded data smaller than encoded\n"));
 | 
			
		||||
@@ -1193,7 +1230,6 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
 | 
			
		||||
		memset(buf + 4 + avpkt->size / 2, 0, buf_sz - 8 - avpkt->size);
 | 
			
		||||
		// don't play with the ac-3 samples
 | 
			
		||||
		AudioEnqueue(buf, buf_sz);
 | 
			
		||||
		// FIXME: handle drift.
 | 
			
		||||
		return;
 | 
			
		||||
	    }
 | 
			
		||||
#if 0
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user