Projects
Essentials
xine-lib-12
xine-lib-ffmpeg-7.patch
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File xine-lib-ffmpeg-7.patch of Package xine-lib-12
Cumulative patches from upstream: https://sourceforge.net/p/xine/xine-lib-1.2/ci/73b833e7fe35 https://sourceforge.net/p/xine/xine-lib-1.2/ci/1e7b18400886 https://sourceforge.net/p/xine/xine-lib-1.2/ci/0a786d63bbdb https://sourceforge.net/p/xine/xine-lib-1.2/ci/6f1000084f60 https://sourceforge.net/p/xine/xine-lib-1.2/ci/771f4ae27e58 diff --git a/src/combined/ffmpeg/demux_avformat.c b/src/combined/ffmpeg/demux_avformat.c index 30b6a2d..a3c2cae 100644 --- a/src/combined/ffmpeg/demux_avformat.c +++ b/src/combined/ffmpeg/demux_avformat.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2022 the xine project + * Copyright (C) 2013-2023 the xine project * Copyright (C) 2013-2020 Petri Hintukainen <phintuka@users.sourceforge.net> * * This file is part of xine, a free video player. @@ -423,8 +423,13 @@ static int find_avformat_streams(avformat_demux_plugin_t *this) { } #ifdef XFF_CODECPAR +# if XFF_AUDIO_CHANNEL_LAYOUT < 2 if (st->codecpar && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate != 0 && st->codecpar->channels != 0) +# else + if (st->codecpar && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && + st->codecpar->sample_rate != 0 && st->codecpar->ch_layout.nb_channels != 0) +# endif #else if (st->codec && st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->codec->sample_rate != 0 && st->codec->channels != 0) @@ -501,7 +506,11 @@ static void send_headers_audio(avformat_demux_plugin_t *this) { buf->size = extradata_size + sizeof(xine_waveformatex); buf->decoder_info[1] = ctx->sample_rate; buf->decoder_info[2] = ctx->bits_per_coded_sample; +#if XFF_AUDIO_CHANNEL_LAYOUT < 2 buf->decoder_info[3] = ctx->channels; +#else + buf->decoder_info[3] = ctx->ch_layout.nb_channels; +#endif buf->decoder_flags = BUF_FLAG_HEADER | BUF_FLAG_STDHEADER | BUF_FLAG_FRAME_END; this->stream->audio_fifo->put (this->stream->audio_fifo, buf); diff --git a/src/combined/ffmpeg/ff_audio_decoder.c b/src/combined/ffmpeg/ff_audio_decoder.c index b542b85..cec1ce6 100644 --- a/src/combined/ffmpeg/ff_audio_decoder.c +++ b/src/combined/ffmpeg/ff_audio_decoder.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2022 the xine project + * Copyright (C) 2001-2024 the xine project * * This file is part of xine, a free video player. * @@ -67,6 +67,7 @@ typedef struct { xine_t *xine; float gain; + int bitexact; } ff_audio_class_t; typedef struct ff_audio_decoder_s { @@ -188,14 +189,25 @@ static int ff_aac_mode_parse (ff_audio_decoder_t *this, uint8_t *buf, int size, xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "ffmpeg_audio_dec: found AAC ADTS syncword after %d bytes\n", i); if (this->buftype == BUF_AUDIO_AAC_LATM) { + uint8_t *ed = NULL; + int es = 0; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "ffmpeg_audio_dec: stream says LATM but is ADTS -> switching decoders\n"); - if (this->decoder_ok) { - pthread_mutex_lock (&ffmpeg_lock); - avcodec_close (this->context); - pthread_mutex_unlock (&ffmpeg_lock); - this->decoder_ok = 0; + pthread_mutex_lock (&ffmpeg_lock); + if (this->context) { + ed = this->context->extradata; + es = this->context->extradata_size; + this->context->extradata = NULL; + this->context->extradata_size = 0; + XFF_FREE_CONTEXT (this->context); } + this->decoder_ok = 0; + this->context = XFF_ALLOC_CONTEXT (); + if (this->context) { + this->context->extradata = ed; + this->context->extradata_size = es; + } + pthread_mutex_unlock (&ffmpeg_lock); this->codec = NULL; ff_audio_open_codec (this, BUF_AUDIO_AAC); } @@ -303,7 +315,11 @@ static void ff_audio_init_codec(ff_audio_decoder_t *this, unsigned int codec_typ this->context->bits_per_sample = this->ff_bits; this->context->sample_rate = this->ff_sample_rate; +#if XFF_AUDIO_CHANNEL_LAYOUT < 2 this->context->channels = this->ff_channels; +#else + this->context->ch_layout.nb_channels = this->ff_channels; +#endif this->context->codec_id = this->codec->id; this->context->codec_type = this->codec->type; this->context->codec_tag = _x_stream_info_get(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC); @@ -345,6 +361,11 @@ static int ff_audio_open_codec(ff_audio_decoder_t *this, unsigned int codec_type return -1; } + if (this->class->bitexact) + this->context->flags |= CODEC_FLAG_BITEXACT; + else + this->context->flags &= ~CODEC_FLAG_BITEXACT; + pthread_mutex_lock (&ffmpeg_lock); if (XFF_AVCODEC_OPEN (this->context, this->codec) < 0) { pthread_mutex_unlock (&ffmpeg_lock); @@ -527,16 +548,75 @@ static void ff_audio_output_close(ff_audio_decoder_t *this) this->ao_mode = 0; } +static unsigned int ff_list_channels (uint8_t *list, uint64_t map) { + unsigned int n, bit; + + for (n = bit = 0; map; map >>= 1, bit++) { + uint32_t b = map & 1; + + list[n] = bit; + n += b; + } + return n; +} + static void ff_map_channels (ff_audio_decoder_t *this) { uint64_t ff_map; + uint8_t ff_list[64]; + unsigned int ff_num; + const char *type = "native"; int caps = this->stream->audio_out->get_capabilities (this->stream->audio_out); +#if XFF_AUDIO_CHANNEL_LAYOUT < 2 + /* safety kludge for very old libavcodec */ -#ifdef AV_CH_FRONT_LEFT +# ifdef AV_CH_FRONT_LEFT ff_map = this->context->channel_layout; if (!ff_map) /* wma2 bug */ -#endif +# endif ff_map = ((uint64_t)1 << this->context->channels) - 1; + ff_num = ff_list_channels (ff_list, ff_map); + +#else /* XFF_AUDIO_CHANNEL_LAYOUT == 2 */ + + ff_num = this->context->ch_layout.nb_channels; + if (ff_num > (int)(sizeof (ff_list) / sizeof (ff_list[0]))) + ff_num = sizeof (ff_list) / sizeof (ff_list[0]); + switch (this->context->ch_layout.order) { + const AVChannelCustom *cmap; + unsigned int i; + + case AV_CHANNEL_ORDER_UNSPEC: + type = "unknown"; + goto _fallback; + + case AV_CHANNEL_ORDER_NATIVE: + ff_map = this->context->ch_layout.u.mask; + if (!ff_map) /* wma2 bug */ + ff_map = ((uint64_t)1 << ff_num) - 1; + ff_num = ff_list_channels (ff_list, ff_map); + break; + + case AV_CHANNEL_ORDER_CUSTOM: + type = "custom"; + if (!(cmap = this->context->ch_layout.u.map)) + goto _fallback; + ff_map = 0; + for (i = 0; i < ff_num; i++) { + ff_list[i] = cmap[i].id; + ff_map |= (uint64_t)1 << ff_list[i]; + } + break; + + default: + type = "unsupported"; + /* fall through */ + _fallback: + ff_map = ((uint64_t)1 << ff_num) - 1; + ff_num = ff_list_channels (ff_list, ff_map); + } + +#endif if ((caps != this->ao_caps) || (ff_map != this->ff_map)) { unsigned int i, j; @@ -562,7 +642,7 @@ static void ff_map_channels (ff_audio_decoder_t *this) { this->ao_caps = caps; this->ff_map = ff_map; - this->ff_channels = this->context->channels; + this->ff_channels = ff_num; /* silence out */ for (i = 0; i < MAX_CHANNELS; i++) @@ -576,20 +656,23 @@ static void ff_map_channels (ff_audio_decoder_t *this) { this->left[0] = this->right[0] = 0; tries = wishlist + 0 * num_modes; } else if (this->ff_channels == 2) { /* stereo */ + /* FIXME: libxine does not yet support audio selection _after_ decoding. + * For now, treat the most common "dual mono" case as stereo. */ name_map[0] = 0; name_map[1] = 1; this->left[0] = 0; this->right[0] = 1; tries = wishlist + 1 * num_modes; } else { - for (i = j = 0; i < sizeof (base_map) / sizeof (base_map[0]); i++) { - if ((ff_map >> i) & 1) { - int8_t target = base_map[i]; - if ((target >= 0) && (this->map[target] < 0)) - this->map[target] = j; - name_map[j] = i; /* for debug output below */ - j++; - } + for (i = 0; i < ff_num; i++) { + int8_t target; + uint32_t num = ff_list[i]; + if (num >= sizeof (base_map) / sizeof (base_map[0])) + continue; + target = base_map[num]; + if ((target >= 0) && (this->map[target] < 0)) + this->map[target] = i; + name_map[i] = num; /* for debug output below */ } this->left[0] = this->map[0] < 0 ? 0 : this->map[0]; this->map[0] = -1; @@ -641,8 +724,8 @@ static void ff_map_channels (ff_audio_decoder_t *this) { "rear center", "side left", "side right" }; - int8_t buf[200]; - int p = sprintf (buf, "ff_audio_dec: channel layout: "); + int8_t buf[256]; + int p = sprintf (buf, "ff_audio_dec: %s channel layout: ", type); int8_t *indx = this->left; for (i = 0; i < 2; i++) { buf[p++] = '['; @@ -730,7 +813,7 @@ static void ff_audio_unparse (ff_audio_decoder_t *this) { #define CLIP_16(v) ((v + 0x8000) & ~0xffff ? (v >> 31) ^ 0x7fff : v) static int ff_audio_decode (ff_audio_decoder_t *this) { - int16_t *decode_buffer = (int16_t *)this->send.buf; + int16_t *decode_buffer = (int16_t *)ASSUME_ALIGNED_2 (this->send.buf, 2); int consumed, got_frame = 0; #if XFF_AUDIO >= 4 float gain = this->class->gain; @@ -805,13 +888,13 @@ static int ff_audio_decode (ff_audio_decoder_t *this) { const stype *p1, *p2, *p3, *p4;\ int i, sstep;\ int8_t *x = idx;\ - int16_t *dptr = (int16_t *)decode_buffer + dindx;\ + int16_t *dptr = decode_buffer + dindx;\ if (planar) {\ - p1 = (stype *)this->av_frame->extended_data[x[0]];\ + p1 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[0]], sizeof (stype));\ if (!p1) break;\ sstep = 1;\ } else {\ - p1 = (stype *)this->av_frame->extended_data[0];\ + p1 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype));\ if (!p1) break;\ p1 += x[0];\ sstep = this->ff_channels;\ @@ -827,10 +910,10 @@ static int ff_audio_decode (ff_audio_decoder_t *this) { break;\ }\ if (planar) {\ - p2 = (stype *)this->av_frame->extended_data[x[1]];\ + p2 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[1]], sizeof (stype));\ if (!p2) break;\ } else\ - p2 = (stype *)this->av_frame->extended_data[0] + x[1];\ + p2 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype)) + x[1];\ if (num == 2) {\ for (i = 0; i < samples; i++) {\ int32_t v = MIX_FIX(*p2);\ @@ -845,10 +928,10 @@ static int ff_audio_decode (ff_audio_decoder_t *this) { break;\ }\ if (planar) {\ - p3 = (stype *)this->av_frame->extended_data[x[2]];\ + p3 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[2]], sizeof (stype));\ if (!p3) break;\ } else\ - p3 = (stype *)this->av_frame->extended_data[0] + x[2];\ + p3 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype)) + x[2];\ if (num == 3) {\ for (i = 0; i < samples; i++) {\ int32_t v = MIX_FIX(*p2);\ @@ -865,10 +948,10 @@ static int ff_audio_decode (ff_audio_decoder_t *this) { break;\ }\ if (planar) {\ - p4 = (stype *)this->av_frame->extended_data[x[3]];\ + p4 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[3]], sizeof (stype));\ if (!p4) break;\ } else\ - p4 = (stype *)this->av_frame->extended_data[0] + x[3];\ + p4 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype)) + x[3];\ for (i = 0; i < samples; i++) {\ int32_t v = MIX_FIX(*p2);\ p2 += sstep;\ @@ -937,13 +1020,13 @@ static int ff_audio_decode (ff_audio_decoder_t *this) { int i, sstep;\ float gain3;\ int8_t *x = idx;\ - int16_t *dptr = (int16_t *)decode_buffer + dindx;\ + int16_t *dptr = decode_buffer + dindx;\ if (planar) {\ - p1 = (stype *)this->av_frame->extended_data[x[0]];\ + p1 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[0]], sizeof (stype));\ if (!p1) break;\ sstep = 1;\ } else {\ - p1 = (stype *)this->av_frame->extended_data[0];\ + p1 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype));\ if (!p1) break;\ p1 += x[0];\ sstep = this->ff_channels;\ @@ -959,10 +1042,10 @@ static int ff_audio_decode (ff_audio_decoder_t *this) { }\ gain3 = gain * 0.7071;\ if (planar) {\ - p2 = (stype *)this->av_frame->extended_data[x[1]];\ + p2 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[1]], sizeof (stype));\ if (!p2) break;\ } else\ - p2 = (stype *)this->av_frame->extended_data[0] + x[1];\ + p2 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype)) + x[1];\ if (num == 2) {\ for (i = 0; i < samples; i++) {\ int32_t v = (*p1) * gain + (*p2) * gain3;\ @@ -974,10 +1057,10 @@ static int ff_audio_decode (ff_audio_decoder_t *this) { break;\ }\ if (planar) {\ - p3 = (stype *)this->av_frame->extended_data[x[2]];\ + p3 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[2]], sizeof (stype));\ if (!p3) break;\ } else\ - p3 = (stype *)this->av_frame->extended_data[0] + x[2];\ + p3 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype)) + x[2];\ if (num == 3) {\ for (i = 0; i < samples; i++) {\ int32_t v = (*p1) * gain + (*p2 + *p3) * gain3;\ @@ -990,10 +1073,10 @@ static int ff_audio_decode (ff_audio_decoder_t *this) { break;\ }\ if (planar) {\ - p4 = (stype *)this->av_frame->extended_data[x[3]];\ + p4 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[3]], sizeof (stype));\ if (!p4) break;\ } else\ - p4 = (stype *)this->av_frame->extended_data[0] + x[3];\ + p4 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype)) + x[3];\ for (i = 0; i < samples; i++) {\ int32_t v = (*p1) * gain + (*p2 + *p3 + *p4) * gain3;\ p1 += sstep;\ @@ -1174,8 +1257,8 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) /* the above codecs output float samples, not 16-bit integers */ int samples = this->send.len / sizeof(float); float gain = this->class->gain; - float *p = (float *)this->decode_buffer; - int16_t *q = (int16_t *)this->decode_buffer; + float *p = (float *)ASSUME_ALIGNED_2 (this->decode_buffer, 4); + int16_t *q = (int16_t *)ASSUME_ALIGNED_2 (this->decode_buffer, 2); int i; for (i = samples; i; i--) { int v = *p++ * gain; @@ -1189,7 +1272,7 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) int samples = this->send.len / (this->ff_channels * 2); int channels = this->ao_channels; int ff_channels = this->ff_channels; - int16_t *p = (int16_t *)this->decode_buffer; + int16_t *p = (int16_t *)ASSUME_ALIGNED_2 (this->decode_buffer, 2); int16_t *q = p; int shift = this->downmix_shift, i, j; /* downmix mono output to stereo first */ @@ -1234,7 +1317,7 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) } /* final mono downmix */ if (channels > this->ao_channels) { - p = (int16_t *)this->decode_buffer; + p = (int16_t *)ASSUME_ALIGNED_2 (this->decode_buffer, 2); q = p; for (i = samples; i; i--) { int v = *p++; @@ -1310,11 +1393,27 @@ static void ff_audio_reset (audio_decoder_t *this_gen) { XFF_FREE_FRAME (this->av_frame); } #endif +#if 1 + avcodec_flush_buffers (this->context); +#else pthread_mutex_lock (&ffmpeg_lock); - avcodec_close (this->context); - if (XFF_AVCODEC_OPEN (this->context, this->codec) < 0) + { + uint8_t *ed = this->context->extradata; + int es = this->context->extradata_size; + this->context->extradata = NULL; + this->context->extradata_size = 0; + XFF_FREE_CONTEXT (this->context); this->decoder_ok = 0; + this->context = XFF_ALLOC_CONTEXT (); + if (this->context) { + this->context->extradata = ed; + this->context->extradata_size = es; + } + } + if (XFF_AVCODEC_OPEN (this->context, this->codec) >= 0) + this->decoder_ok = 1; pthread_mutex_unlock (&ffmpeg_lock); +#endif } ff_audio_reset_parser(this); @@ -1352,20 +1451,20 @@ static void ff_audio_dispose (audio_decoder_t *this_gen) { XFF_FREE_FRAME (this->av_frame); } #endif - pthread_mutex_lock (&ffmpeg_lock); - avcodec_close (this->context); - pthread_mutex_unlock (&ffmpeg_lock); } + pthread_mutex_lock (&ffmpeg_lock); + if (this->context) { + _x_freep (&this->context->extradata); + this->context->extradata_size = 0; + XFF_FREE_CONTEXT (this->context); + } + pthread_mutex_unlock (&ffmpeg_lock); ff_audio_output_close(this); xine_free_aligned (this->buf); xine_free_aligned (this->decode_buffer); - _x_freep (&this->context->extradata); - this->context->extradata_size = 0; - XFF_FREE_CONTEXT (this->context); - XFF_PACKET_UNREF (this->avpkt); xine_pts_queue_delete (&this->pts_queue); @@ -1447,6 +1546,12 @@ static void dispose_audio_class (audio_decoder_class_t *this_gen) { free (this); } +static void ff_bitexact_cb (void *user_data, xine_cfg_entry_t *entry) { + ff_audio_class_t *class = (ff_audio_class_t *)user_data; + + class->bitexact = entry->num_value; +} + void *init_audio_plugin (xine_t *xine, const void *data) { ff_audio_class_t *this ; @@ -1474,5 +1579,12 @@ void *init_audio_plugin (xine_t *xine, const void *data) { 10, ff_gain_cb, this) / (float)20); + this->bitexact = xine->config->register_bool (xine->config, + "audio.processing.ffmpeg_bitexact", 0, + _("Let FFmpeg use precise but slower math"), + _("Get slightly better sound, at the expense of speed.\n" + "Takes effect with next stream."), + 10, ff_bitexact_cb, this); + return this; } diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c index 54efc05..5a10225 100644 --- a/src/combined/ffmpeg/ff_video_decoder.c +++ b/src/combined/ffmpeg/ff_video_decoder.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2022 the xine project + * Copyright (C) 2001-2024 the xine project * * This file is part of xine, a free video player. * @@ -89,6 +89,11 @@ # define ENABLE_EMMS #endif +/* +#undef XFF_AVCODEC_SLICE_TABLE +#define XFF_AVCODEC_SLICE_TABLE 1 +*/ + #define VIDEOBUFSIZE (128*1024) #define SLICE_BUFFER_SIZE (1194*1024) @@ -128,6 +133,7 @@ struct ff_video_decoder_s { int64_t pts; int64_t last_pts; + int64_t tagged_pts; int video_step; int reported_video_step; uint8_t pts_tag_pass; @@ -147,11 +153,11 @@ struct ff_video_decoder_s { int bufsize; int size; int skipframes; - +#if XFF_AVCODEC_SLICE_TABLE == 1 int *slice_offset_table; int slice_offset_size; int slice_offset_pos; - +#endif AVFrame *av_frame; AVFrame *av_frame2; AVCodecContext *context; @@ -237,6 +243,13 @@ struct ff_video_decoder_s { #if XFF_VIDEO > 1 XFF_PACKET_DECL (avpkt); #endif + +#if XFF_AVCODEC_SLICE_TABLE == 2 + uint8_t *temp_buf; + uint32_t temp_size; + int slice_num; + uint8_t slice_table[1 + 256 * 8]; +#endif }; /* import color matrix names */ @@ -551,7 +564,9 @@ static int get_buffer_vaapi_vld (AVCodecContext *context, AVFrame *av_frame) # ifdef XFF_FRAME_AGE av_frame->age = 1; # endif +#ifdef XFF_AVCODEC_REORDERED_OPAQUE av_frame->reordered_opaque = context->reordered_opaque; +#endif ffsf = ffsf_new (this); if (!ffsf) @@ -862,7 +877,9 @@ static int get_buffer (AVCodecContext *context, AVFrame *av_frame) # endif /* take over pts for this frame to have it reordered */ +#ifdef XFF_AVCODEC_REORDERED_OPAQUE av_frame->reordered_opaque = context->reordered_opaque; +#endif return 0; } @@ -1142,9 +1159,13 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type) if (this->codec->id == CODEC_ID_VC1 && (!this->bih.biWidth || !this->bih.biHeight)) { /* VC1 codec must be re-opened with correct width and height. */ - avcodec_close(this->context); - - if (XFF_AVCODEC_OPEN (this->context, this->codec) < 0) { + if (this->context) { + _x_freep (&this->context->extradata); + this->context->extradata_size = 0; + XFF_FREE_CONTEXT (this->context); + } + this->context = XFF_ALLOC_CONTEXT (); + if (!(this->context && XFF_AVCODEC_OPEN (this->context, this->codec) >= 0)) { pthread_mutex_unlock(&ffmpeg_lock); xprintf (this->stream->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: couldn't open decoder (pass 2)\n")); @@ -1211,6 +1232,11 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type) /* dont want initial AV_NOPTS_VALUE here */ this->context->reordered_opaque = 0; #endif + +#ifdef XFF_AVCODEC_FRAME_PTS + this->context->time_base.num = 1; + this->context->time_base.den = 90000 << 8; +#endif } #ifdef ENABLE_VAAPI @@ -1398,7 +1424,7 @@ static void ff_setup_rgb2yuy2 (ff_video_decoder_t *this, int pix_fmt) { #if defined(AV_PIX_FMT_YUV420P9) || defined(AV_PIX_FMT_YUV420P10) static void ff_get_deep_color (uint8_t *src, int sstride, uint8_t *dest, int dstride, int width, int height, uint8_t *tab) { - uint16_t *p = (uint16_t *) src; + uint16_t *p = (uint16_t *)ASSUME_ALIGNED_2 (src, 2); uint8_t *q = dest; int spad = sstride / 2 - width; int dpad = dstride - width; @@ -1769,10 +1795,9 @@ static void ff_handle_header_buffer (ff_video_decoder_t *this, buf_element_t *bu this->size += buf->size; if (buf->decoder_flags & BUF_FLAG_FRAME_END) { - int codec_type; + uint32_t codec_type = buf->type & 0xFFFF0000; lprintf ("header complete\n"); - codec_type = buf->type & 0xFFFF0000; if (buf->decoder_flags & BUF_FLAG_STDHEADER) { @@ -1804,22 +1829,24 @@ static void ff_handle_header_buffer (ff_video_decoder_t *this, buf_element_t *bu #ifdef XFF_AVCODEC_SUB_ID this->context->sub_id = _X_BE_32(&this->buf[30]); #endif - this->context->extradata_size = this->size - 26; - if (this->context->extradata_size < 8) { - this->context->extradata_size= 8; - this->context->extradata = calloc(1, this->context->extradata_size + - AV_INPUT_BUFFER_PADDING_SIZE); - ((uint32_t *)this->context->extradata)[0] = 0; - if (codec_type == BUF_VIDEO_RV10) - ((uint32_t *)this->context->extradata)[1] = 0x10000000; - else - ((uint32_t *)this->context->extradata)[1] = 0x10003001; + if (this->size < 8 + 26) { + uint32_t *b = calloc (1, 8 + AV_INPUT_BUFFER_PADDING_SIZE); + if (b) { + this->context->extradata_size = 8; + this->context->extradata = (uint8_t *)b; + b[0] = 0; + if (codec_type == BUF_VIDEO_RV10) + b[1] = 0x10000000; + else + b[1] = 0x10003001; + } } else { - this->context->extradata = malloc(this->context->extradata_size + - AV_INPUT_BUFFER_PADDING_SIZE); - memcpy(this->context->extradata, this->buf + 26, - this->context->extradata_size); - memset(this->context->extradata + this->context->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + this->context->extradata = malloc (this->size - 26 + AV_INPUT_BUFFER_PADDING_SIZE); + if (this->context->extradata) { + this->context->extradata_size = this->size - 26; + memcpy (this->context->extradata, this->buf + 26, this->context->extradata_size); + memset (this->context->extradata + this->context->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + } } xprintf(this->stream->xine, XINE_VERBOSITY_LOG, @@ -1896,33 +1923,44 @@ static void ff_handle_special_buffer (ff_video_decoder_t *this, buf_element_t *b #endif } else if (buf->decoder_info[1] == BUF_SPECIAL_RV_CHUNK_TABLE) { - /* o dear. Multiple decoding threads use individual contexts. - av_decode_video2 () does only copy the _pointer_ to the offsets, - not the offsets themselves. So we must not overwrite anything - that another thread has not yet read. */ - int i, l, total; - - lprintf("BUF_SPECIAL_RV_CHUNK_TABLE\n"); - l = buf->decoder_info[2] + 1; - - total = l * this->class->thread_count; - if (total < SLICE_OFFSET_SIZE) - total = SLICE_OFFSET_SIZE; - if (total > this->slice_offset_size) { - this->slice_offset_table = realloc (this->slice_offset_table, total * sizeof (int)); - this->slice_offset_size = total; - } + { +#if XFF_AVCODEC_SLICE_TABLE == 1 + /* o dear. Multiple decoding threads use individual contexts. + * av_decode_video2 () does only copy the _pointer_ to the offsets, + * not the offsets themselves. So we must not overwrite anything + * that another thread has not yet read. */ + int i, l, total; + + lprintf("BUF_SPECIAL_RV_CHUNK_TABLE\n"); + l = buf->decoder_info[2] + 1; + + total = l * this->class->thread_count; + if (total < SLICE_OFFSET_SIZE) + total = SLICE_OFFSET_SIZE; + if (total > this->slice_offset_size) { + this->slice_offset_table = realloc (this->slice_offset_table, total * sizeof (int)); + this->slice_offset_size = total; + } - if (this->slice_offset_pos + l > this->slice_offset_size) - this->slice_offset_pos = 0; - this->context->slice_offset = this->slice_offset_table + this->slice_offset_pos; - this->context->slice_count = l; + if (this->slice_offset_pos + l > this->slice_offset_size) + this->slice_offset_pos = 0; + this->context->slice_offset = this->slice_offset_table + this->slice_offset_pos; + this->context->slice_count = l; - lprintf ("slice_count=%d\n", l); - for (i = 0; i < l; i++) { - this->slice_offset_table[this->slice_offset_pos++] = - ((uint32_t *)buf->decoder_info_ptr[2])[(2 * i) + 1]; - lprintf("slice_offset[%d]=%d\n", i, this->context->slice_offset[i]); + lprintf ("slice_count=%d\n", l); + for (i = 0; i < l; i++) { + this->slice_offset_table[this->slice_offset_pos++] = + ((uint32_t *)buf->decoder_info_ptr[2])[(2 * i) + 1]; + lprintf("slice_offset[%d]=%d\n", i, this->context->slice_offset[i]); + } +#elif XFF_AVCODEC_SLICE_TABLE == 2 + /* (count-1):1, 1:4, (offs[0]):4, 1:4, (offs[1]:4, ... just in front of the frame bitstream. + * reverse engineered from ffmpeg/libavcodec/rv34.c. they seem to expect no + * external use of rv decoders, and did not document this. */ + this->slice_table[0] = buf->decoder_info[2]; + this->slice_num = this->slice_table[0] + 1; + memcpy (this->slice_table + 1, buf->decoder_info_ptr[2], 8 * this->slice_num); +#endif } } } @@ -1957,7 +1995,26 @@ static int64_t ff_tag_pts (ff_video_decoder_t *this, int64_t pts) { return (pts * 256) | this->pts_tag_pass; } -static int64_t ff_untag_pts (ff_video_decoder_t *this, int64_t pts) { +static int64_t ff_untag_pts (ff_video_decoder_t *this, AVFrame *av_frame) { + int64_t pts; +#if defined(XFF_AVCODEC_FRAME_PTS) + pts = (av_frame->pts != AV_NOPTS_VALUE) ? av_frame->pts : 0; +# if defined(XFF_AVCODEC_REORDERED_OPAQUE) + /* paranoia !!! */ + if (pts != av_frame->reordered_opaque) { + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": WARNING: frame pts %" PRId64 " != reordered_opaque %" PRId64 ".\n", + pts, av_frame->reordered_opaque); + pts = av_frame->reordered_opaque; + } + av_frame->reordered_opaque = 0; +# endif +#elif defined(XFF_AVCODEC_REORDERED_OPAQUE) + pts = av_frame->reordered_opaque; + av_frame->reordered_opaque = 0; +#else + pts = this->tagged_pts; +#endif if ((uint8_t)(pts & 0xff) == this->pts_tag_pass) { /* restore sign. */ return pts >> 8; @@ -1969,6 +2026,7 @@ static int64_t ff_untag_pts (ff_video_decoder_t *this, int64_t pts) { static int decode_video_wrapper (ff_video_decoder_t *this, AVFrame *av_frame, int *err, void *buf, size_t buf_size) { + uint32_t tsize = 0; int len; #if ENABLE_VAAPI @@ -1978,11 +2036,36 @@ static int decode_video_wrapper (ff_video_decoder_t *this, } #endif /* ENABLE_VAAPI */ +#if XFF_AVCODEC_SLICE_TABLE == 2 + if ((this->slice_num > 0) && buf) { + uint32_t nsize; + tsize = 1 + this->slice_num * 8; + nsize = tsize + buf_size + AV_INPUT_BUFFER_PADDING_SIZE; + if (this->temp_size < nsize) { + nsize = nsize * 3 / 2; + free (this->temp_buf); + this->temp_buf = malloc (nsize); + if (!this->temp_buf) + nsize = 0; + this->temp_size = nsize; + nsize = tsize + buf_size + AV_INPUT_BUFFER_PADDING_SIZE; + } + if (this->temp_size >= nsize) { + memcpy (this->temp_buf, this->slice_table, tsize); + memcpy (this->temp_buf + tsize, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE); + buf = this->temp_buf; + } + this->slice_num = 0; + } +#endif + #if XFF_VIDEO > 1 this->avpkt->data = buf; - this->avpkt->size = buf_size; + this->avpkt->size = buf_size + tsize; this->avpkt->flags = AV_PKT_FLAG_KEY; - +# ifdef XFF_AVCODEC_FRAME_PTS + this->avpkt->pts = this->tagged_pts; +# endif # if XFF_PALETTE == 2 || XFF_PALETTE == 3 if (buf && this->palette_changed) { uint8_t *sd = av_packet_new_side_data (this->avpkt, AV_PKT_DATA_PALETTE, 256 * 4); @@ -2092,9 +2175,14 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu #endif /* apply valid pts to first frame _starting_ thereafter only */ - if (this->pts && !this->context->reordered_opaque) { - this->context->reordered_opaque = - this->av_frame->reordered_opaque = ff_tag_pts (this, this->pts); + if (this->pts && !this->tagged_pts) { + this->tagged_pts = ff_tag_pts (this, this->pts); +#ifdef XFF_AVCODEC_REORDERED_OPAQUE + this->context->reordered_opaque = this->av_frame->reordered_opaque = this->tagged_pts; +#endif +#ifdef XFF_AVCODEC_FRAME_PTS + this->av_frame->pts = this->tagged_pts; +#endif this->pts = 0; } @@ -2205,9 +2293,11 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu img->top_field_first = this->av_frame->top_field_first; /* get back reordered pts */ - img->pts = ff_untag_pts (this, this->av_frame->reordered_opaque); - this->av_frame->reordered_opaque = 0; + img->pts = ff_untag_pts (this, this->av_frame); + this->tagged_pts = 0; +#ifdef XFF_AVCODEC_REORDERED_OPAQUE this->context->reordered_opaque = 0; +#endif if (this->av_frame->repeat_pict) img->duration = this->video_step * 3 / 2; @@ -2328,9 +2418,14 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { } if (this->size == 0) { + this->tagged_pts = ff_tag_pts (this, this->pts); /* take over pts when we are about to buffer a frame */ - this->av_frame->reordered_opaque = ff_tag_pts(this, this->pts); - this->context->reordered_opaque = ff_tag_pts(this, this->pts); +#ifdef XFF_AVCODEC_REORDERED_OPAQUE + this->av_frame->reordered_opaque = this->context->reordered_opaque = this->tagged_pts; +#endif +#ifdef XFF_AVCODEC_FRAME_PTS + this->av_frame->pts = this->tagged_pts; +#endif this->pts = 0; } @@ -2403,7 +2498,10 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { need_unref = 1; #endif /* reset consumed pts value */ - this->context->reordered_opaque = ff_tag_pts(this, 0); + this->tagged_pts = ff_tag_pts (this, 0); +#ifdef XFF_AVCODEC_REORDERED_OPAQUE + this->context->reordered_opaque = this->tagged_pts; +#endif if (err) { @@ -2434,13 +2532,16 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { this->size -= len; if (this->size > 0) { - ff_check_bufsize(this, this->size); memmove (this->buf, &chunk_buf[offset], this->size); chunk_buf = this->buf; - /* take over pts for next access unit */ - this->av_frame->reordered_opaque = ff_tag_pts(this, this->pts); - this->context->reordered_opaque = ff_tag_pts(this, this->pts); + this->tagged_pts = ff_tag_pts (this, this->pts); +#ifdef XFF_AVCODEC_REORDERED_OPAQUE + this->av_frame->reordered_opaque = this->context->reordered_opaque = this->tagged_pts; +#endif +#ifdef XFF_AVCODEC_FRAME_PTS + this->av_frame->pts = this->tagged_pts; +#endif this->pts = 0; } } @@ -2557,11 +2658,10 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { ff_convert_frame(this, img, this->av_frame); } - img->pts = ff_untag_pts(this, this->av_frame->reordered_opaque); - this->av_frame->reordered_opaque = 0; + img->pts = ff_untag_pts(this, this->av_frame); - /* workaround for weird 120fps streams */ - if( video_step_to_use == 750 ) { + /* workaround for weird 120fps streams, as well as some rv20 with frame duration 3pts. */ + if (video_step_to_use <= 750) { /* fallback to the VIDEO_PTS_MODE */ video_step_to_use = 0; } @@ -2598,8 +2698,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { this->output_format, VO_BOTH_FIELDS|this->frame_flags); /* set PTS to allow early syncing */ - img->pts = ff_untag_pts(this, this->av_frame->reordered_opaque); - this->av_frame->reordered_opaque = 0; + img->pts = ff_untag_pts(this, this->av_frame); img->duration = video_step_to_use; @@ -2781,9 +2880,9 @@ static void ff_flush_internal (ff_video_decoder_t *this, int display) { ff_convert_frame (this, img, this->av_frame2); } - img->pts = ff_untag_pts (this, this->av_frame2->reordered_opaque); + img->pts = ff_untag_pts (this, this->av_frame2); - if (video_step_to_use == 750) + if (video_step_to_use <= 750) video_step_to_use = 0; img->duration = this->av_frame2->repeat_pict ? video_step_to_use * 3 / 2 : video_step_to_use; img->progressive_frame = !this->av_frame2->interlaced_frame; @@ -2887,6 +2986,9 @@ static void ff_reset (video_decoder_t *this_gen) { mpeg_parser_reset(this->mpeg_parser); /* this->pts_tag_pass = 0; */ +#if XFF_AVCODEC_SLICE_TABLE == 2 + this->slice_num = 0; +#endif } static void ff_dispose (video_decoder_t *this_gen) { @@ -2899,10 +3001,15 @@ static void ff_dispose (video_decoder_t *this_gen) { rgb2yuy2_free (this->rgb2yuy2); if (this->decoder_ok) { + uint8_t *ed; pthread_mutex_lock(&ffmpeg_lock); - avcodec_close (this->context); + ed = this->context->extradata; + this->context->extradata = NULL; + this->context->extradata_size = 0; + XFF_FREE_CONTEXT (this->context); pthread_mutex_unlock(&ffmpeg_lock); + _x_freep (&ed); #ifdef ENABLE_DIRECT_RENDERING ff_free_dr1_frames (this, 1); @@ -2910,17 +3017,18 @@ static void ff_dispose (video_decoder_t *this_gen) { this->stream->video_out->close(this->stream->video_out, this->stream); this->decoder_ok = 0; - } - - if (this->slice_offset_table) - free (this->slice_offset_table); - - if (this->context) { + } else if (this->context) { _x_freep (&this->context->extradata); this->context->extradata_size = 0; XFF_FREE_CONTEXT (this->context); } +#if XFF_AVCODEC_SLICE_TABLE == 1 + free (this->slice_offset_table); +#elif XFF_AVCODEC_SLICE_TABLE == 2 + free (this->temp_buf); +#endif + #if XFF_VIDEO > 1 XFF_PACKET_UNREF (this->avpkt); #endif @@ -3007,21 +3115,25 @@ static video_decoder_t *ff_video_open_plugin (video_decoder_class_t *class_gen, this->decoder_ok = 0; this->aspect_ratio = 0; this->pts_tag_pass = 0; -#ifdef HAVE_POSTPROC +# ifdef HAVE_POSTPROC this->pp_quality = 0; this->our_context = NULL; this->our_mode = NULL; -#endif +# endif this->mpeg_parser = NULL; this->set_stream_info = 0; this->rgb2yuy2 = NULL; -#ifdef ENABLE_VAAPI +# ifdef ENABLE_VAAPI this->accel = NULL; this->accel_img = NULL; -#endif -#if XFF_VIDEO == 3 +# endif +# if XFF_VIDEO == 3 this->flush_packet_sent = 0; -#endif +# endif +# if XFF_AVCODEC_SLICE_TABLE == 2 + this->temp_size = 0; + this->temp_buf = NULL; +# endif #endif this->video_decoder.decode_data = ff_decode_data; diff --git a/src/combined/ffmpeg/ffmpeg_compat.h b/src/combined/ffmpeg/ffmpeg_compat.h index 803ace2..01096a7 100644 --- a/src/combined/ffmpeg/ffmpeg_compat.h +++ b/src/combined/ffmpeg/ffmpeg_compat.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2022 the xine project + * Copyright (C) 2000-2024 the xine project * * This file is part of xine, a unix video player. * @@ -54,9 +54,16 @@ #endif /* reordered_opaque appeared in libavcodec 51.68.0 */ -#define XFF_AVCODEC_REORDERED_OPAQUE -#if LIBAVCODEC_VERSION_INT < XFF_INT_VERSION(51,68,0) -# undef XFF_AVCODEC_REORDERED_OPAQUE +#if LIBAVCODEC_VERSION_INT >= XFF_INT_VERSION(51,68,0) && LIBAVCODEC_VERSION_INT < XFF_INT_VERSION(60,0,0) +# define XFF_AVCODEC_REORDERED_OPAQUE +#else +# undef XFF_AVCODEC_REORDERED_OPAQUE +#endif + +#if LIBAVCODEC_VERSION_INT >= XFF_INT_VERSION(58,33,100) +# define XFF_AVCODEC_FRAME_PTS +#else +# undef XFF_AVCODEC_FRAME_PTS #endif /* colorspace and color_range were added before 52.29.0 */ @@ -132,6 +139,14 @@ # define XFF_PALETTE 3 #endif +#if LIBAVCODEC_VERSION_INT < XFF_INT_VERSION(59,42,100) +/* AVCodecContext.slice_{offset,count} */ +# define XFF_AVCODEC_SLICE_TABLE 1 +#else +/* inline offset table before the frame. */ +# define XFF_AVCODEC_SLICE_TABLE 2 +#endif + #if LIBAVCODEC_VERSION_INT < XFF_INT_VERSION(59,0,100) /** << revise this */ # define XFF_VAAPI 1 /** << libavcodec/vaapi.h */ #else @@ -210,9 +225,11 @@ #endif #if LIBAVCODEC_VERSION_INT < XFF_INT_VERSION(55,63,100) -# define XFF_FREE_CONTEXT(pp) do {av_free(pp); pp = NULL;} while (0) +# define XFF_FREE_CONTEXT(pp) do {if (pp) avcodec_close (pp); av_free (pp); pp = NULL;} while (0) +#elif LIBAVCODEC_VERSION_INT < XFF_INT_VERSION(58,33,100) +# define XFF_FREE_CONTEXT(pp) do {if (pp) avcodec_close (pp); avcodec_free_context (&(pp));} while (0) #else -# define XFF_FREE_CONTEXT(pp) avcodec_free_context(&(pp)) +# define XFF_FREE_CONTEXT(pp) avcodec_free_context (&(pp)) #endif #if LIBAVCODEC_VERSION_INT < XFF_INT_VERSION(54,59,100) @@ -303,4 +320,3 @@ #endif /* defined(LIBAVCODEC_VERSION_INT) */ #endif /* XINE_AVCODEC_COMPAT_H */ - diff --git a/src/dxr3/ffmpeg_encoder.c b/src/dxr3/ffmpeg_encoder.c index 42dee3a..f45d60d 100644 --- a/src/dxr3/ffmpeg_encoder.c +++ b/src/dxr3/ffmpeg_encoder.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2022 the xine project + * Copyright (C) 2000-2024 the xine project * * This file is part of xine, a unix video player. * @@ -127,10 +127,8 @@ static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) unsigned char use_quantizer; if (this->context) { - avcodec_close(this->context); - free(this->context); + XFF_FREE_CONTEXT (this->context); free(this->picture); - this->context = NULL; this->picture = NULL; } @@ -344,10 +342,8 @@ static int lavc_on_unneeded(dxr3_driver_t *drv) #if XFF_ENCVIDEO > 1 XFF_PACKET_UNREF (this->pkt); #endif - avcodec_close(this->context); XFF_FREE_CONTEXT (this->context); free(this->picture); - this->context = NULL; this->picture = NULL; } return 1;
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.