mirror of
https://github.com/jojo61/vdr-plugin-softhdcuvid.git
synced 2023-10-10 13:37:41 +02:00
improve records cutting
This commit is contained in:
parent
b3d3caec41
commit
333b720c65
227
codec.c
227
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; i<frame->nb_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; i<frame->nb_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
365
softhddev.c
365
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
|
||||
|
92
video.c
92
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.
|
||||
///
|
||||
|
Loading…
Reference in New Issue
Block a user