From 333b720c65d8a7b0da18621f383bc3f110f4ffb2 Mon Sep 17 00:00:00 2001 From: jojo61 Date: Mon, 10 Dec 2018 13:10:58 +0100 Subject: [PATCH] improve records cutting --- codec.c | 227 ++++++++++---------------------- softhddev.c | 365 ++++++++++++++++++++++++++-------------------------- video.c | 92 +++++++++---- 3 files changed, 317 insertions(+), 367 deletions(-) diff --git a/codec.c b/codec.c index a3c35e2..32b1e5d 100644 --- a/codec.c +++ b/codec.c @@ -490,8 +490,9 @@ next_part: if (ret >= 0) { // one is avail. got_frame = 1; } - else + else { got_frame = 0; + } if (got_frame) { // frame completed #ifdef FFMPEG_WORKAROUND_ARTIFACTS @@ -1350,75 +1351,38 @@ void CodecAudioEnqueue(AudioDecoder * audio_decoder, int16_t * data, int count) int myavcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples, int *frame_size_ptr, - AVPacket *avpkt) + AVPacket *avpkt) { - AVFrame *frame = av_frame_alloc(); - int ret, got_frame = 0; + AVFrame *frame = av_frame_alloc(); + int ret, got_frame = 0; - if (!frame) - return AVERROR(ENOMEM); -#if 0 - if (avctx->get_buffer != avcodec_default_get_buffer) { - av_log(avctx, AV_LOG_ERROR, "Custom get_buffer() for use with" - "avcodec_decode_audio3() detected.ar *) samples Overriding with avcodec_default_get_buffer\n"); - av_log(avctx, AV_LOG_ERROR, "Please port your application to " - "avcodec_decode_audio4()\n"); - avctx->get_buffer = avcodec_default_get_buffer; - avctx->release_buffer = avcodec_default_release_buffer; - } -#endif - ret = avcodec_decode_audio4(avctx, frame, &got_frame, avpkt); + if (!frame) + return AVERROR(ENOMEM); + + ret = avcodec_decode_audio4(avctx, frame, &got_frame, avpkt); - if (ret >= 0 && got_frame) { -#if 0 - int ch, plane_size; - int planar = av_sample_fmt_is_planar(avctx->sample_fmt); - int data_size = av_samples_get_buffer_size(&plane_size, avctx->channels, - frame->nb_samples, - avctx->sample_fmt, 1); - if (*frame_size_ptr < data_size) { - Debug(3, "output buffer size is too small for " - "the current frame (%d < %d)\n", *frame_size_ptr, data_size); - av_frame_free(&frame); - return AVERROR(EINVAL); - } -#endif -#if 1 - int i,ch; - int planar = av_sample_fmt_is_planar(avctx->sample_fmt); - int data_size = av_get_bytes_per_sample(avctx->sample_fmt); - if (data_size < 0) { - /* This should not occur, checking just for paranoia */ - fprintf(stderr, "Failed to calculate data size\n"); - exit(1); - } - for (i=0; inb_samples; i++) - for (ch=0; ch < avctx->channels; ch++) { - memcpy(samples,frame->extended_data[ch]+data_size*i,data_size); - samples = (char *) samples + data_size; + if (ret >= 0 && got_frame) { + int i,ch; + int planar = av_sample_fmt_is_planar(avctx->sample_fmt); + int data_size = av_get_bytes_per_sample(avctx->sample_fmt); + if (data_size < 0) { + /* This should not occur, checking just for paranoia */ + fprintf(stderr, "Failed to calculate data size\n"); + exit(1); } -#endif -//Debug(3,"data_size %d nb_samples %d sample_fmt %d channels %d planar %d\n",data_size,frame->nb_samples,avctx->sample_fmt,avctx->channels,planar); - -#if 0 - memcpy(samples, frame->extended_data[0], plane_size); -// memcpy(samples, frame->data[0], plane_size); - - if (planar && avctx->channels > 1) { - uint8_t *out = ((uint8_t *)samples) + plane_size; - for (ch = 1; ch < avctx->channels; ch++) { - memcpy(out, frame->extended_data[ch], plane_size); -// memcpy(out, frame->data[ch], plane_size); - out += plane_size; - } - } -#endif - *frame_size_ptr = data_size * avctx->channels * frame->nb_samples; - } else { - *frame_size_ptr = 0; - } - av_frame_free(&frame); - return ret; + for (i=0; inb_samples; i++) { + for (ch=0; ch < avctx->channels; ch++) { + memcpy(samples,frame->extended_data[ch]+data_size*i,data_size); + samples = (char *) samples + data_size; + } + } + //Debug(3,"data_size %d nb_samples %d sample_fmt %d channels %d planar %d\n",data_size,frame->nb_samples,avctx->sample_fmt,avctx->channels,planar); + *frame_size_ptr = data_size * avctx->channels * frame->nb_samples; + } else { + *frame_size_ptr = 0; + } + av_frame_free(&frame); + return ret; } @@ -1444,110 +1408,59 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt) buf_sz = sizeof(buf); l = myavcodec_decode_audio3(audio_ctx, buf, &buf_sz, (AVPacket *) avpkt); if (avpkt->size != l) { - if (l == AVERROR(EAGAIN)) { - Error(_("codec: latm\n")); - return; - } - if (l < 0) { // no audio frame could be decompressed - Error(_("codec: error audio data\n")); - return; - } - Error(_("codec: error more than one frame data\n")); + if (l == AVERROR(EAGAIN)) { + Error(_("codec: latm\n")); + return; + } + if (l < 0) { // no audio frame could be decompressed + Error(_("codec: error audio data\n")); + return; + } + Error(_("codec: error more than one frame data\n")); } // update audio clock if (avpkt->pts != (int64_t) AV_NOPTS_VALUE) { - CodecAudioSetClock(audio_decoder, avpkt->pts); + CodecAudioSetClock(audio_decoder, avpkt->pts); } // FIXME: must first play remainings bytes, than change and play new. if (audio_decoder->Passthrough != CodecPassthrough - || audio_decoder->SampleRate != audio_ctx->sample_rate - || audio_decoder->Channels != audio_ctx->channels) { - CodecAudioUpdateFormat(audio_decoder); + || audio_decoder->SampleRate != audio_ctx->sample_rate + || audio_decoder->Channels != audio_ctx->channels) { + CodecAudioUpdateFormat(audio_decoder); } 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; + // 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; - // FIXME: libav-0.7.2 crash here - outlen = - audio_resample(audio_decoder->ReSample, outbuf, buf, buf_sz); + // FIXME: libav-0.7.2 crash here + outlen = audio_resample(audio_decoder->ReSample, outbuf, buf, buf_sz); #ifdef DEBUG - if (outlen != buf_sz) { - Debug(3, "codec/audio: possible fixed ffmpeg\n"); - } + if (outlen != buf_sz) { + Debug(3, "codec/audio: possible fixed ffmpeg\n"); + } #endif - if (outlen) { - // outlen seems to be wrong in ffmpeg-0.9 - outlen /= audio_decoder->Channels * - av_get_bytes_per_sample(audio_ctx->sample_fmt); - outlen *= - audio_decoder->HwChannels * - av_get_bytes_per_sample(audio_ctx->sample_fmt); - Debug(4, "codec/audio: %d -> %d\n", buf_sz, outlen); - CodecAudioEnqueue(audio_decoder, outbuf, outlen); - } - } else { - if (CodecAudioPassthroughHelper(audio_decoder, avpkt)) { - return; - } -#if 0 - // - // old experimental code - // - if (1) { - // FIXME: need to detect dts - // copy original data for output - // FIXME: buf is sint - buf[0] = 0x72; - buf[1] = 0xF8; - buf[2] = 0x1F; - buf[3] = 0x4E; - buf[4] = 0x00; - switch (avpkt->size) { - case 512: - buf[5] = 0x0B; - break; - case 1024: - buf[5] = 0x0C; - break; - case 2048: - buf[5] = 0x0D; - break; - default: - Debug(3, - "codec/audio: dts sample burst not supported\n"); - buf[5] = 0x00; - break; + if (outlen) { + // outlen seems to be wrong in ffmpeg-0.9 + outlen /= audio_decoder->Channels * + av_get_bytes_per_sample(audio_ctx->sample_fmt); + outlen *= + audio_decoder->HwChannels * + av_get_bytes_per_sample(audio_ctx->sample_fmt); + Debug(4, "codec/audio: %d -> %d\n", buf_sz, outlen); + CodecAudioEnqueue(audio_decoder, outbuf, outlen); + } + } else { + if (CodecAudioPassthroughHelper(audio_decoder, avpkt)) { + return; + } + + CodecAudioEnqueue(audio_decoder, buf, buf_sz); } - buf[6] = (avpkt->size * 8); - buf[7] = (avpkt->size * 8) >> 8; - //buf[8] = 0x0B; - //buf[9] = 0x77; - //printf("%x %x\n", avpkt->data[0],avpkt->data[1]); - // swab? - memcpy(buf + 8, avpkt->data, avpkt->size); - memset(buf + 8 + avpkt->size, 0, buf_sz - 8 - avpkt->size); - } else if (1) { - // FIXME: need to detect mp2 - // FIXME: mp2 passthrough - // see softhddev.c version/layer - // 0x04 mpeg1 layer1 - // 0x05 mpeg1 layer23 - // 0x06 mpeg2 ext - // 0x07 mpeg2.5 layer 1 - // 0x08 mpeg2.5 layer 2 - // 0x09 mpeg2.5 layer 3 - } - // DTS HD? - // True HD? -#endif - CodecAudioEnqueue(audio_decoder, buf, buf_sz); - } } } diff --git a/softhddev.c b/softhddev.c index 92d1143..219c0af 100644 --- a/softhddev.c +++ b/softhddev.c @@ -1022,29 +1022,29 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id) // channel switch: SetAudioChannelDevice: SetDigitalAudioDevice: if (SkipAudio || !MyAudioDecoder) { // skip audio - return size; + return size; } if (StreamFreezed) { // stream freezed - return 0; + return 0; } if (NewAudioStream) { - // this clears the audio ringbuffer indirect, open and setup does it - CodecAudioClose(MyAudioDecoder); - AudioFlushBuffers(); - AudioSetBufferTime(ConfigAudioBufferTime); - AudioCodecID = AV_CODEC_ID_NONE; - AudioChannelID = -1; - NewAudioStream = 0; + // this clears the audio ringbuffer indirect, open and setup does it + CodecAudioClose(MyAudioDecoder); + AudioFlushBuffers(); + AudioSetBufferTime(ConfigAudioBufferTime); + AudioCodecID = AV_CODEC_ID_NONE; + AudioChannelID = -1; + NewAudioStream = 0; } // hard limit buffer full: don't overrun audio buffers on replay if (AudioFreeBytes() < AUDIO_MIN_BUFFER_FREE) { - return 0; + return 0; } #ifdef USE_SOFTLIMIT // soft limit buffer full if (AudioSyncStream && VideoGetBuffers(AudioSyncStream) > 3 && AudioUsedBytes() > AUDIO_MIN_BUFFER_FREE * 2) { - return 0; + return 0; } #endif // PES header 0x00 0x00 0x01 ID @@ -1052,8 +1052,8 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id) // must be a PES start code if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) { - Error(_("[softhddev] invalid PES audio packet\n")); - return size; + Error(_("[softhddev] invalid PES audio packet\n")); + return size; } n = data[8]; // header size @@ -1067,93 +1067,93 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id) } if (data[7] & 0x80 && n >= 5) { - AudioAvPkt->pts = - (int64_t) (data[9] & 0x0E) << 29 | data[10] << 22 | (data[11] & - 0xFE) << 14 | data[12] << 7 | (data[13] & 0xFE) >> 1; - //Debug(3, "audio: pts %#012" PRIx64 "\n", AudioAvPkt->pts); + AudioAvPkt->pts = + (int64_t) (data[9] & 0x0E) << 29 | data[10] << 22 | (data[11] & + 0xFE) << 14 | data[12] << 7 | (data[13] & 0xFE) >> 1; + //Debug(3, "audio: pts %#012" PRIx64 "\n", AudioAvPkt->pts); } if (0) { // dts is unused - if (data[7] & 0x40) { - AudioAvPkt->dts = - (int64_t) (data[14] & 0x0E) << 29 | data[15] << 22 | (data[16] - & 0xFE) << 14 | data[17] << 7 | (data[18] & 0xFE) >> 1; - Debug(3, "audio: dts %#012" PRIx64 "\n", AudioAvPkt->dts); - } + if (data[7] & 0x40) { + AudioAvPkt->dts = + (int64_t) (data[14] & 0x0E) << 29 | data[15] << 22 | (data[16] + & 0xFE) << 14 | data[17] << 7 | (data[18] & 0xFE) >> 1; + Debug(3, "audio: dts %#012" PRIx64 "\n", AudioAvPkt->dts); + } } p = data + 9 + n; n = size - 9 - n; // skip pes header if (n + AudioAvPkt->stream_index > AudioAvPkt->size) { - Fatal(_("[softhddev] audio buffer too small\n")); - AudioAvPkt->stream_index = 0; + Fatal(_("[softhddev] audio buffer too small\n")); + AudioAvPkt->stream_index = 0; } if (AudioChannelID != id) { // id changed audio track changed - AudioChannelID = id; - AudioCodecID = AV_CODEC_ID_NONE; - Debug(3, "audio/demux: new channel id\n"); + AudioChannelID = id; + AudioCodecID = AV_CODEC_ID_NONE; + Debug(3, "audio/demux: new channel id\n"); } // Private stream + LPCM ID if ((id & 0xF0) == 0xA0) { - if (n < 7) { - Error(_("[softhddev] invalid LPCM audio packet %d bytes\n"), size); - return size; - } - if (AudioCodecID != AV_CODEC_ID_PCM_DVD) { - static int samplerates[] = { 48000, 96000, 44100, 32000 }; - int samplerate; - int channels; - int bits_per_sample; + if (n < 7) { + Error(_("[softhddev] invalid LPCM audio packet %d bytes\n"), size); + return size; + } + if (AudioCodecID != AV_CODEC_ID_PCM_DVD) { + static int samplerates[] = { 48000, 96000, 44100, 32000 }; + int samplerate; + int channels; + int bits_per_sample; - Debug(3, "[softhddev]%s: LPCM %d sr:%d bits:%d chan:%d\n", - __FUNCTION__, id, p[5] >> 4, (((p[5] >> 6) & 0x3) + 4) * 4, - (p[5] & 0x7) + 1); - CodecAudioClose(MyAudioDecoder); + Debug(3, "[softhddev]%s: LPCM %d sr:%d bits:%d chan:%d\n", + __FUNCTION__, id, p[5] >> 4, (((p[5] >> 6) & 0x3) + 4) * 4, + (p[5] & 0x7) + 1); + CodecAudioClose(MyAudioDecoder); - bits_per_sample = (((p[5] >> 6) & 0x3) + 4) * 4; - if (bits_per_sample != 16) { - Error(_ - ("[softhddev] LPCM %d bits per sample aren't supported\n"), - bits_per_sample); - // FIXME: handle unsupported formats. - } - samplerate = samplerates[p[5] >> 4]; - channels = (p[5] & 0x7) + 1; + bits_per_sample = (((p[5] >> 6) & 0x3) + 4) * 4; + if (bits_per_sample != 16) { + Error(_ + ("[softhddev] LPCM %d bits per sample aren't supported\n"), + bits_per_sample); + // FIXME: handle unsupported formats. + } + samplerate = samplerates[p[5] >> 4]; + channels = (p[5] & 0x7) + 1; - // FIXME: ConfigAudioBufferTime + x - AudioSetBufferTime(400); - AudioSetup(&samplerate, &channels, 0); - if (samplerate != samplerates[p[5] >> 4]) { - Error(_("[softhddev] LPCM %d sample-rate is unsupported\n"), - samplerates[p[5] >> 4]); - // FIXME: support resample - } - if (channels != (p[5] & 0x7) + 1) { - Error(_("[softhddev] LPCM %d channels are unsupported\n"), - (p[5] & 0x7) + 1); - // FIXME: support resample - } - //CodecAudioOpen(MyAudioDecoder, AV_CODEC_ID_PCM_DVD); - AudioCodecID = AV_CODEC_ID_PCM_DVD; - } + // FIXME: ConfigAudioBufferTime + x + AudioSetBufferTime(400); + AudioSetup(&samplerate, &channels, 0); + if (samplerate != samplerates[p[5] >> 4]) { + Error(_("[softhddev] LPCM %d sample-rate is unsupported\n"), + samplerates[p[5] >> 4]); + // FIXME: support resample + } + if (channels != (p[5] & 0x7) + 1) { + Error(_("[softhddev] LPCM %d channels are unsupported\n"), + (p[5] & 0x7) + 1); + // FIXME: support resample + } + //CodecAudioOpen(MyAudioDecoder, AV_CODEC_ID_PCM_DVD); + AudioCodecID = AV_CODEC_ID_PCM_DVD; + } - if (AudioAvPkt->pts != (int64_t) AV_NOPTS_VALUE) { - AudioSetClock(AudioAvPkt->pts); - AudioAvPkt->pts = AV_NOPTS_VALUE; - } - swab(p + 7, AudioAvPkt->data, n - 7); - AudioEnqueue(AudioAvPkt->data, n - 7); + if (AudioAvPkt->pts != (int64_t) AV_NOPTS_VALUE) { + AudioSetClock(AudioAvPkt->pts); + AudioAvPkt->pts = AV_NOPTS_VALUE; + } + swab(p + 7, AudioAvPkt->data, n - 7); + AudioEnqueue(AudioAvPkt->data, n - 7); - return size; + return size; } // DVD track header if ((id & 0xF0) == 0x80 && (p[0] & 0xF0) == 0x80) { - p += 4; - n -= 4; // skip track header - if (AudioCodecID == AV_CODEC_ID_NONE) { - // FIXME: ConfigAudioBufferTime + x - AudioSetBufferTime(400); - } + p += 4; + n -= 4; // skip track header + if (AudioCodecID == AV_CODEC_ID_NONE) { + // FIXME: ConfigAudioBufferTime + x + AudioSetBufferTime(400); + } } // append new packet, to partial old data memcpy(AudioAvPkt->data + AudioAvPkt->stream_index, p, n); @@ -1162,73 +1162,73 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id) n = AudioAvPkt->stream_index; p = AudioAvPkt->data; while (n >= 5) { - int r; - unsigned codec_id; + int r; + unsigned codec_id; - // 4 bytes 0xFFExxxxx Mpeg audio - // 3 bytes 0x56Exxx AAC LATM audio - // 5 bytes 0x0B77xxxxxx AC-3 audio - // 6 bytes 0x0B77xxxxxxxx E-AC-3 audio - // 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio - // PCM audio can't be found - r = 0; - codec_id = AV_CODEC_ID_NONE; // keep compiler happy - if (id != 0xbd && FastMpegCheck(p)) { - r = MpegCheck(p, n); - codec_id = AV_CODEC_ID_MP2; - } - if (id != 0xbd && !r && FastLatmCheck(p)) { - r = LatmCheck(p, n); - codec_id = AV_CODEC_ID_AAC_LATM; - } - if ((id == 0xbd || (id & 0xF0) == 0x80) && !r && FastAc3Check(p)) { - r = Ac3Check(p, n); - codec_id = AV_CODEC_ID_AC3; - if (r > 0 && p[5] > (10 << 3)) { - codec_id = AV_CODEC_ID_EAC3; - } - /* faster ac3 detection at end of pes packet (no improvemnts) - if (AudioCodecID == codec_id && -r - 2 == n) { - r = n; - } - */ - } - if (id != 0xbd && !r && FastAdtsCheck(p)) { - r = AdtsCheck(p, n); - codec_id = AV_CODEC_ID_AAC; - } - if (r < 0) { // need more bytes - break; - } - if (r > 0) { - AVPacket avpkt[1]; + // 4 bytes 0xFFExxxxx Mpeg audio + // 3 bytes 0x56Exxx AAC LATM audio + // 5 bytes 0x0B77xxxxxx AC-3 audio + // 6 bytes 0x0B77xxxxxxxx E-AC-3 audio + // 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio + // PCM audio can't be found + r = 0; + codec_id = AV_CODEC_ID_NONE; // keep compiler happy + if (id != 0xbd && FastMpegCheck(p)) { + r = MpegCheck(p, n); + codec_id = AV_CODEC_ID_MP2; + } + if (id != 0xbd && !r && FastLatmCheck(p)) { + r = LatmCheck(p, n); + codec_id = AV_CODEC_ID_AAC_LATM; + } + if ((id == 0xbd || (id & 0xF0) == 0x80) && !r && FastAc3Check(p)) { + r = Ac3Check(p, n); + codec_id = AV_CODEC_ID_AC3; + if (r > 0 && p[5] > (10 << 3)) { + codec_id = AV_CODEC_ID_EAC3; + } + /* faster ac3 detection at end of pes packet (no improvemnts) + if (AudioCodecID == codec_id && -r - 2 == n) { + r = n; + } + */ + } + if (id != 0xbd && !r && FastAdtsCheck(p)) { + r = AdtsCheck(p, n); + codec_id = AV_CODEC_ID_AAC; + } + if (r < 0) { // need more bytes + break; + } + if (r > 0) { + AVPacket avpkt[1]; - // new codec id, close and open new - if (AudioCodecID != codec_id) { - CodecAudioClose(MyAudioDecoder); - CodecAudioOpen(MyAudioDecoder, codec_id); - AudioCodecID = codec_id; - } - av_init_packet(avpkt); - avpkt->data = (void *)p; - avpkt->size = r; - avpkt->pts = AudioAvPkt->pts; - avpkt->dts = AudioAvPkt->dts; - // FIXME: not aligned for ffmpeg - CodecAudioDecode(MyAudioDecoder, avpkt); - AudioAvPkt->pts = AV_NOPTS_VALUE; - AudioAvPkt->dts = AV_NOPTS_VALUE; - p += r; - n -= r; - continue; - } - ++p; - --n; + // new codec id, close and open new + if (AudioCodecID != codec_id) { + CodecAudioClose(MyAudioDecoder); + CodecAudioOpen(MyAudioDecoder, codec_id); + AudioCodecID = codec_id; + } + av_init_packet(avpkt); + avpkt->data = (void *)p; + avpkt->size = r; + avpkt->pts = AudioAvPkt->pts; + avpkt->dts = AudioAvPkt->dts; + // FIXME: not aligned for ffmpeg + CodecAudioDecode(MyAudioDecoder, avpkt); + AudioAvPkt->pts = AV_NOPTS_VALUE; + AudioAvPkt->dts = AV_NOPTS_VALUE; + p += r; + n -= r; + continue; + } + ++p; + --n; } // copy remaining bytes to start of packet if (n) { - memmove(AudioAvPkt->data, p, n); + memmove(AudioAvPkt->data, p, n); } AudioAvPkt->stream_index = n; @@ -1252,31 +1252,31 @@ int PlayTsAudio(const uint8_t * data, int size) static TsDemux tsdx[1]; if (SkipAudio || !MyAudioDecoder) { // skip audio - return size; + return size; } if (StreamFreezed) { // stream freezed - return 0; + return 0; } if (NewAudioStream) { - // this clears the audio ringbuffer indirect, open and setup does it - CodecAudioClose(MyAudioDecoder); - AudioFlushBuffers(); - // max time between audio packets 200ms + 24ms hw buffer - AudioSetBufferTime(ConfigAudioBufferTime); - AudioCodecID = AV_CODEC_ID_NONE; - AudioChannelID = -1; - NewAudioStream = 0; - PesReset(PesDemuxAudio); + // this clears the audio ringbuffer indirect, open and setup does it + CodecAudioClose(MyAudioDecoder); + AudioFlushBuffers(); + // max time between audio packets 200ms + 24ms hw buffer + AudioSetBufferTime(ConfigAudioBufferTime); + AudioCodecID = AV_CODEC_ID_NONE; + AudioChannelID = -1; + NewAudioStream = 0; + PesReset(PesDemuxAudio); } // hard limit buffer full: don't overrun audio buffers on replay if (AudioFreeBytes() < AUDIO_MIN_BUFFER_FREE) { - return 0; + return 0; } #ifdef USE_SOFTLIMIT // soft limit buffer full if (AudioSyncStream && VideoGetBuffers(AudioSyncStream) > 3 && AudioUsedBytes() > AUDIO_MIN_BUFFER_FREE * 2) { - return 0; + return 0; } #endif @@ -2680,12 +2680,12 @@ void StillPicture(const uint8_t * data, int size) // might be called in Suspended Mode if (!MyVideoStream->Decoder || MyVideoStream->SkipStream) { - return; + return; } // must be a PES start code if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) { - Error(_("[softhddev] invalid still video packet\n")); - return; + Error(_("[softhddev] invalid still video packet\n")); + return; } #ifdef STILL_DEBUG InStillPicture = 1; @@ -2697,15 +2697,15 @@ void StillPicture(const uint8_t * data, int size) if (MyVideoStream->CodecID == AV_CODEC_ID_NONE) { - // FIXME: should detect codec, see PlayVideo - Error(_("[softhddev] no codec known for still picture\n")); + // FIXME: should detect codec, see PlayVideo + Error(_("[softhddev] no codec known for still picture\n")); } // FIXME: can check video backend, if a frame was produced. // output for max reference frames #ifdef STILL_DEBUG fprintf(stderr, "still-picture\n"); #endif - for (i = 0; i < (MyVideoStream->CodecID == AV_CODEC_ID_HEVC ? 8 : 12); ++i) { + for (i = 0; i < (MyVideoStream->CodecID == AV_CODEC_ID_HEVC ? 8 : 8); ++i) { const uint8_t *split; int n; @@ -2715,38 +2715,38 @@ void StillPicture(const uint8_t * data, int size) n = size; // split the I-frame into single pes packets do { - int len; + int len; #ifdef DEBUG - if (split[0] || split[1] || split[2] != 0x01) { - Error(_("[softhddev] invalid still video packet\n")); - break; - } + if (split[0] || split[1] || split[2] != 0x01) { + Error(_("[softhddev] invalid still video packet\n")); + break; + } #endif - len = (split[4] << 8) + split[5]; - if (!len || len + 6 > n) { + len = (split[4] << 8) + split[5]; + if (!len || len + 6 > n) { + if ((split[3] & 0xF0) == 0xE0) { + // video only + while (!PlayVideo3(MyVideoStream, split, n)) { // feed remaining bytes + } + } + break; + } if ((split[3] & 0xF0) == 0xE0) { - // video only - while (!PlayVideo3(MyVideoStream, split, n)) { // feed remaining bytes + // video only + while (!PlayVideo3(MyVideoStream, split, len + 6)) { // feed it + } } - } - break; - } - if ((split[3] & 0xF0) == 0xE0) { - // video only - while (!PlayVideo3(MyVideoStream, split, len + 6)) { // feed it - } - } - split += 6 + len; - n -= 6 + len; + split += 6 + len; + n -= 6 + len; } while (n > 6); VideoNextPacket(MyVideoStream, MyVideoStream->CodecID); // terminate last packet } else { // ES packet if (MyVideoStream->CodecID != AV_CODEC_ID_MPEG2VIDEO) { - VideoNextPacket(MyVideoStream, AV_CODEC_ID_NONE); // close last stream - MyVideoStream->CodecID = AV_CODEC_ID_MPEG2VIDEO; + VideoNextPacket(MyVideoStream, AV_CODEC_ID_NONE); // close last stream + MyVideoStream->CodecID = AV_CODEC_ID_MPEG2VIDEO; } VideoEnqueue(MyVideoStream, AV_NOPTS_VALUE,AV_NOPTS_VALUE, data, size); } @@ -2761,11 +2761,10 @@ void StillPicture(const uint8_t * data, int size) } // wait for empty buffers - for (i = 0; VideoGetBuffers(MyVideoStream) && i < 30; ++i) { + for (i = 0; VideoGetBuffers(MyVideoStream) && i < 50; ++i) { usleep(10 * 1000); } - Debug(3, "[softhddev]%s: buffers %d %dms\n", __FUNCTION__, - VideoGetBuffers(MyVideoStream), i * 10); + Debug(3, "[softhddev]%s: buffers %d %dms\n", __FUNCTION__, VideoGetBuffers(MyVideoStream), i * 10); #ifdef STILL_DEBUG InStillPicture = 0; #endif diff --git a/video.c b/video.c index 1d562e6..e477b2d 100644 --- a/video.c +++ b/video.c @@ -429,6 +429,7 @@ static float VideoColorBlindnessFaktor = 1.0f; static xcb_atom_t WmDeleteWindowAtom; ///< WM delete message atom static xcb_atom_t NetWmState; ///< wm-state message atom static xcb_atom_t NetWmStateFullscreen; ///< fullscreen wm-state message atom +static xcb_atom_t NetWmStateAbove; #ifdef DEBUG extern uint32_t VideoSwitch; ///< ticks for channel switch @@ -2203,7 +2204,6 @@ createTextureDst(CuvidDecoder * decoder,int anz, unsigned int size_x, unsigned i struct pl_tex *tex; struct pl_image *img; struct pl_plane *pl; - const float black[4] = { 0.0f,0.0f,0.0f,1.0f}; //printf("Create textures and planes %d %d\n",size_x,size_y); Debug(3,"video/vulkan: create %d Textures Format %s w %d h %d \n",anz,PixFmt==AV_PIX_FMT_NV12?"NV12":"P010",size_x,size_y); @@ -2584,7 +2584,7 @@ static enum AVPixelFormat Cuvid_get_format(CuvidDecoder * decoder, decoder->SurfacesNeeded = VIDEO_SURFACES_MAX + 1; CuvidSetupOutput(decoder); #ifdef PLACEBO // dont show first frame -// decoder->newchannel = 1; + decoder->newchannel = 1; #endif } @@ -3146,7 +3146,7 @@ extern void P016ToBgra32(uint8_t *dpNv12, int nNv12Pitch, uint8_t *dpBgra, int n extern void ResizeNv12(unsigned char *dpDstNv12, int nDstPitch, int nDstWidth, int nDstHeight, unsigned char *dpSrcNv12, int nSrcPitch, int nSrcWidth, int nSrcHeight, unsigned char* dpDstNv12UV); extern void ResizeP016(unsigned char *dpDstP016, int nDstPitch, int nDstWidth, int nDstHeight, unsigned char *dpSrcP016, int nSrcPitch, int nSrcWidth, int nSrcHeight, unsigned char* dpDstP016UV); extern void cudaLaunchNV12toARGBDrv(uint32_t *d_srcNV12, size_t nSourcePitch,uint32_t *d_dstARGB, size_t nDestPitch,uint32_t width, uint32_t height,CUstream streamID); - +void VideoSetAbove(); /// /// Render a ffmpeg frame. /// @@ -3250,6 +3250,7 @@ Debug(3,"fmt %02d:%02d width %d:%d hight %d:%d\n",decoder->ColorSpace,frame->co av_frame_free(&output); } #endif + // copy to texture generateCUDAImage(decoder,surface,frame,w,h,decoder->PixFmt==AV_PIX_FMT_NV12?1:2); @@ -3375,9 +3376,8 @@ static void CuvidMixVideo(CuvidDecoder * decoder, int level) VkImage Image; struct pl_image *img; bool ok; - const float black[4] = { 0.0f,0.0f,0.0f,1.0f}; #endif - + static int last; int current; VdpRect video_src_rect; VdpRect dst_rect; @@ -3489,7 +3489,7 @@ static void CuvidMixVideo(CuvidDecoder * decoder, int level) } // Source crop if (VideoScalerTest) { // right side defnied scaler - pl_tex_clear(p->gpu,target->fbo,black); // clear frame + pl_tex_clear(p->gpu,target->fbo,(float[4]){0}); // clear frame img->src_rect.x0 = video_src_rect.x1/2+1; img->src_rect.y0 = video_src_rect.y0; img->src_rect.x1 = video_src_rect.x1; @@ -3550,7 +3550,7 @@ static void CuvidMixVideo(CuvidDecoder * decoder, int level) colors.gamma = VideoGamma; if (ovl) { - pl_tex_clear(p->gpu,target->fbo,black); // clear frame + pl_tex_clear(p->gpu,target->fbo,(float[4]){0}); // clear frame target->overlays = ovl; target->num_overlays = 1; } else { @@ -3558,6 +3558,11 @@ static void CuvidMixVideo(CuvidDecoder * decoder, int level) target->num_overlays = 0; } + if (decoder->newchannel && current == 0 ) + return; + + decoder->newchannel = 0; + if (!pl_render_image(p->renderer, &decoder->pl_images[current], target, &render_params)) { Fatal(_("Failed rendering frame!\n")); } @@ -3606,7 +3611,7 @@ void make_osd_overlay(int x, int y, int width, int height) { pl = &osdoverlay; if (pl->plane.texture) { -// pl_tex_clear(p->gpu,pl->plane.texture,black); + pl_tex_clear(p->gpu,pl->plane.texture,(float[4]){0}); pl_tex_destroy(p->gpu,&pl->plane.texture); } @@ -3624,7 +3629,7 @@ void make_osd_overlay(int x, int y, int width, int height) { }); // make overlay - pl_tex_clear(p->gpu,pl->plane.texture,black); + pl_tex_clear(p->gpu,pl->plane.texture,(float[4]){0}); pl->plane.components = 4; pl->plane.shift_x = 0.0f; pl->plane.shift_y = 0.0f; @@ -3661,7 +3666,7 @@ static void CuvidDisplayFrame(void) struct pl_swapchain_frame frame; struct pl_render_target target; bool ok; - + const float black[4] = { 0.0f,0.0f,0.0f,1.0f}; #endif @@ -3758,6 +3763,7 @@ static void CuvidDisplayFrame(void) } #ifdef PLACEBO if (OsdShown == 1) { // New OSD opened +// VideoSetAbove(); pthread_mutex_lock(&OSDMutex); make_osd_overlay(OSDx,OSDy,OSDxsize,OSDysize); if (posd) { @@ -3771,11 +3777,12 @@ static void CuvidDisplayFrame(void) } if (OsdShown == 2) { +// VideoSetAbove(); CuvidMixVideo(decoder, i, &target, &osdoverlay); - } else { + } else { CuvidMixVideo(decoder, i, &target, NULL); } - + #else CuvidMixVideo(decoder, i); #endif @@ -3966,17 +3973,17 @@ static void CuvidSyncDecoder(CuvidDecoder * decoder) // 60Hz: repeat every 5th field if (Video60HzMode && !(decoder->FramesDisplayed % 6)) { - if (audio_clock == (int64_t) AV_NOPTS_VALUE || video_clock == (int64_t) AV_NOPTS_VALUE) { + if (audio_clock == (int64_t) AV_NOPTS_VALUE || video_clock == (int64_t) AV_NOPTS_VALUE) { + goto out; + } + // both clocks are known + if (audio_clock + VideoAudioDelay <= video_clock + 25 * 90) { goto out; - } - // both clocks are known - if (audio_clock + VideoAudioDelay <= video_clock + 25 * 90) { - goto out; - } - // out of sync: audio before video - if (!decoder->TrickSpeed) { - goto skip_sync; - } + } + // out of sync: audio before video + if (!decoder->TrickSpeed) { + goto skip_sync; + } } // TrickSpeed if (decoder->TrickSpeed) { @@ -4007,7 +4014,8 @@ static void CuvidSyncDecoder(CuvidDecoder * decoder) diff = video_clock - audio_clock - VideoAudioDelay; diff = (decoder->LastAVDiff + diff) / 2; decoder->LastAVDiff = diff; - +//if (abs(diff/90) > 30) +// printf("Diff %d\n",diff/90); if (abs(diff) > 5000 * 90) { // more than 5s err = CuvidMessage(2, "video: audio/video difference too big\n"); } else if (diff > 100 * 90) { @@ -4027,7 +4035,7 @@ static void CuvidSyncDecoder(CuvidDecoder * decoder) CuvidAdvanceDecoderFrame(decoder); // filled = atomic_read(&decoder->SurfacesFilled); // Debug(3,"hinter drop frame filled %d\n",atomic_read(&decoder->SurfacesFilled)); - decoder->SyncCounter = 1; + decoder->SyncCounter = 1;;; } #if defined(DEBUG) || defined(AV_INFO) if (!decoder->SyncCounter && decoder->StartCounter < 1000) { @@ -4273,7 +4281,7 @@ static void CuvidDisplayHandlerThread(void) // all decoder buffers are full // and display is not preempted // speed up filling display queue, wait on display queue empty - if (!allfull) { + if (!allfull && !decoder->TrickSpeed) { clock_gettime(CLOCK_MONOTONIC, &nowtime); // time for one frame over? if ((nowtime.tv_sec - CuvidFrameTime.tv_sec) * 1000 * 1000 * 1000 + @@ -5744,7 +5752,15 @@ static void VideoCreateWindow(xcb_window_t parent, xcb_visualid_t visual, uint8_ NetWmStateFullscreen = reply->atom; free(reply); } - + + if ((reply = + xcb_intern_atom_reply(Connection, xcb_intern_atom(Connection, 0, + sizeof("_NET_WM_STATE_ABOVE") - 1, + "_NET_WM_STATE_ABOVE"), NULL))) { + NetWmStateAbove = reply->atom; + free(reply); + } + xcb_map_window(Connection, VideoWindow); xcb_flush(Connection); @@ -6080,7 +6096,8 @@ void VideoSetFullscreen(int onoff) event.data.data32[0] = XCB_EWMH_WM_STATE_REMOVE; } event.data.data32[1] = NetWmStateFullscreen; - + event.data.data32[2] = NetWmStateAbove; + xcb_send_event(Connection, XCB_SEND_EVENT_DEST_POINTER_WINDOW, DefaultRootWindow(XlibDisplay), XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | @@ -6090,6 +6107,27 @@ void VideoSetFullscreen(int onoff) } } +void VideoSetAbove() +{ + if (XlibDisplay) { // needs running connection + xcb_client_message_event_t event; + + memset(&event, 0, sizeof(event)); + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.window = VideoWindow; + event.type = NetWmState; + event.data.data32[0] = XCB_EWMH_WM_STATE_ADD; + event.data.data32[1] = NetWmStateAbove; + + xcb_send_event(Connection, XCB_SEND_EVENT_DEST_POINTER_WINDOW, + DefaultRootWindow(XlibDisplay), + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (void *)&event); + Debug(3, "video/x11: send fullscreen message %x %x\n", + event.data.data32[0], event.data.data32[1]); + } +} /// /// Set deinterlace mode. ///