diff -Naurpb xine-lib-1.2-04-19-08.org/contrib/a52dec/parse.c xine-lib-1.2-04.19.08/contrib/a52dec/parse.c --- xine-lib-1.2-04-19-08.org/contrib/a52dec/parse.c 2008-04-19 18:58:24.276177000 -0400 +++ xine-lib-1.2-04.19.08/contrib/a52dec/parse.c 2008-05-28 10:01:17.308841000 -0400 @@ -262,7 +262,7 @@ static int parse_deltba (a52_state_t * s { int deltnseg, deltlen, delta, j; - memset (deltba, 0, 50); + xine_fast_memset (deltba, 0, 50); deltnseg = bitstream_get (state, 3); j = 0; @@ -721,11 +721,11 @@ int a52_block (a52_state_t * state) if (do_bit_alloc) { if (zero_snr_offsets (nfchans, state)) { - memset (state->cpl_expbap.bap, 0, sizeof (state->cpl_expbap.bap)); + xine_fast_memset (state->cpl_expbap.bap, 0, sizeof (state->cpl_expbap.bap)); for (i = 0; i < nfchans; i++) - memset (state->fbw_expbap[i].bap, 0, + xine_fast_memset (state->fbw_expbap[i].bap, 0, sizeof (state->fbw_expbap[i].bap)); - memset (state->lfe_expbap.bap, 0, sizeof (state->lfe_expbap.bap)); + xine_fast_memset (state->lfe_expbap.bap, 0, sizeof (state->lfe_expbap.bap)); } else { if (state->chincpl && (do_bit_alloc & 64)) /* cplinu */ a52_bit_allocate (state, &state->cplba, state->cplstrtbnd, diff -Naurpb xine-lib-1.2-04-19-08.org/include/xine/audio_out.h xine-lib-1.2-04.19.08/include/xine/audio_out.h --- xine-lib-1.2-04-19-08.org/include/xine/audio_out.h 2008-04-19 18:58:31.465705000 -0400 +++ xine-lib-1.2-04.19.08/include/xine/audio_out.h 2008-04-19 18:47:35.634601000 -0400 @@ -349,7 +349,7 @@ int _x_ao_channels2mode( int channels ) #define AO_CTRL_FLUSH_BUFFERS 2 /* above that value audio frames are discarded */ -#define AO_MAX_GAP 15000 +#define AO_MAX_GAP 150000 #ifdef __cplusplus } diff -Naurpb xine-lib-1.2-04-19-08.org/include/xine/xineutils.h xine-lib-1.2-04.19.08/include/xine/xineutils.h --- xine-lib-1.2-04-19-08.org/include/xine/xineutils.h 2008-04-19 18:58:31.610716000 -0400 +++ xine-lib-1.2-04.19.08/include/xine/xineutils.h 2008-05-27 17:50:13.000000000 -0400 @@ -587,6 +587,8 @@ typedef union { extern void *(* xine_fast_memcpy)(void *to, const void *from, size_t len) XINE_PROTECTED; +extern void *xine_fast_memset(void * to, int val, size_t len) XINE_PROTECTED; + #ifdef HAVE_XINE_INTERNAL_H /* Benchmark available memcpy methods */ void xine_probe_fast_memcpy(xine_t *xine) XINE_PROTECTED; diff -Naurpb xine-lib-1.2-04-19-08.org/src/audio_dec/xine_a52_decoder.c xine-lib-1.2-04.19.08/src/audio_dec/xine_a52_decoder.c --- xine-lib-1.2-04-19-08.org/src/audio_dec/xine_a52_decoder.c 2008-04-19 18:58:31.973743000 -0400 +++ xine-lib-1.2-04.19.08/src/audio_dec/xine_a52_decoder.c 2008-04-19 18:47:35.635601000 -0400 @@ -238,6 +238,8 @@ static void a52dec_decode_frame (a52dec_ a52_output_flags = this->a52_flags_map[this->a52_flags & A52_CHANNEL_MASK]; + if (a52_output_flags == 0x0) + a52_output_flags = 0x2; if (a52_frame (this->a52_state, this->frame_buffer, &a52_output_flags, @@ -308,6 +310,8 @@ static void a52dec_decode_frame (a52dec_ break; } + if (output_mode == 0x0) + output_mode = 0x8; switch (output_mode) { case AO_CAP_MODE_MONO: float_to_int (&samples[0], int_samples+(i*256), 1); diff -Naurpb xine-lib-1.2-04-19-08.org/src/audio_dec/xine_mad_decoder.c xine-lib-1.2-04.19.08/src/audio_dec/xine_mad_decoder.c --- xine-lib-1.2-04-19-08.org/src/audio_dec/xine_mad_decoder.c 2008-04-19 18:58:31.977743000 -0400 +++ xine-lib-1.2-04.19.08/src/audio_dec/xine_mad_decoder.c 2008-04-23 11:55:03.891430000 -0400 @@ -110,6 +110,7 @@ static void mad_discontinuity (audio_dec mad_decoder_t *this = (mad_decoder_t *) this_gen; + lprintf("mad_discontinuity\n"); this->pts = 0; } @@ -151,7 +152,7 @@ static void mad_decode_data (audio_decod mad_decoder_t *this = (mad_decoder_t *) this_gen; int bytes_in_buffer_at_pts; - lprintf ("decode data, size: %d, decoder_flags: %d\n", buf->size, buf->decoder_flags); + lprintf ("decode data, size: %d, decoder_flags: %d, pts=%"PRId64"\n", buf->size, buf->decoder_flags, buf->pts); if (buf->size>(INPUT_BUF_SIZE-this->bytes_in_buffer)) { xprintf (this->xstream->xine, XINE_VERBOSITY_DEBUG, @@ -172,7 +173,6 @@ static void mad_decode_data (audio_decod } bytes_in_buffer_at_pts = this->bytes_in_buffer; - xine_fast_memcpy (&this->buffer[this->bytes_in_buffer], buf->content, buf->size); this->bytes_in_buffer += buf->size; @@ -183,9 +183,8 @@ static void mad_decode_data (audio_decod mad_stream_buffer (&this->stream, this->buffer, this->bytes_in_buffer); - - if (this->bytes_in_buffer < MAD_MIN_SIZE) - return; +/* if (this->bytes_in_buffer < MAD_MIN_SIZE) + return;*/ while (1) { @@ -268,7 +267,7 @@ static void mad_decode_data (audio_decod mad_synth_frame (&this->synth, &this->frame); if ( (buf->decoder_flags & BUF_FLAG_PREVIEW) == 0 ) { - + lprintf("no preview\n"); unsigned int nchannels, nsamples; mad_fixed_t const *left_ch, *right_ch; struct mad_pcm *pcm = &this->synth.pcm; @@ -304,6 +303,7 @@ static void mad_decode_data (audio_decod bitrate = _x_stream_info_get(this->xstream, XINE_STREAM_INFO_AUDIO_BITRATE); lprintf("offset %d bps\n", bitrate); } + lprintf("buf->pts=%"PRId64"\n",buf->pts); audio_buffer->vpts = buf->pts; if (audio_buffer->vpts && (bitrate > 0)) { pts_offset = (bytes_in_buffer_at_pts * 8 * 90) / (bitrate / 1000); diff -Naurpb xine-lib-1.2-04-19-08.org/src/audio_out/audio_alsa_out.c xine-lib-1.2-04.19.08/src/audio_out/audio_alsa_out.c --- xine-lib-1.2-04-19-08.org/src/audio_out/audio_alsa_out.c 2008-04-19 18:58:32.037747000 -0400 +++ xine-lib-1.2-04.19.08/src/audio_out/audio_alsa_out.c 2008-04-24 09:58:25.643430000 -0400 @@ -267,7 +267,7 @@ static long ao_alsa_get_volume_from_perc static void XINE_FORMAT_PRINTF(5, 6) error_callback(const char *file, int line, const char *function, int err, const char *fmt, ...) { -#ifdef DEBUG +//#ifdef DEBUG va_list args; char *buf = NULL; @@ -276,7 +276,7 @@ static void XINE_FORMAT_PRINTF(5, 6) va_end(args); printf("%s: %s() %s.\n", file, function, buf); free(buf); -#endif +//#endif } /* @@ -311,6 +311,8 @@ static int ao_alsa_open(ao_driver_t *thi snd_pcm_sw_params_alloca(&swparams); err = snd_output_stdio_attach(&jcd_out, stdout, 0); + if (mode == 0x0) + mode = 0x8; switch (mode) { case AO_CAP_MODE_MONO: this->num_channels = 1; @@ -341,10 +343,10 @@ static int ao_alsa_open(ao_driver_t *thi return 0; } -#ifdef ALSA_LOG +//#ifdef ALSA_LOG printf("audio_alsa_out: Audio Device name = %s\n",pcm_device); printf("audio_alsa_out: Number of channels = %d\n",this->num_channels); -#endif +//#endif if (this->audio_fd) { xine_log (this->class->xine, XINE_LOG_MSG, _("audio_alsa_out:Already open...WHY!")); @@ -360,6 +362,37 @@ static int ao_alsa_open(ao_driver_t *thi * open audio device * When switching to surround, dmix blocks the device some time, so we just keep trying for 0.8sec. */ + + printf("mode=%d, audio_fd=%d, pcm_device=%s, direction=%d, open_mode=%d\n",mode, this->audio_fd, pcm_device, direction, open_mode); + + const char *pcm_dig = "iec958:AES0=0x4,AES1=0x82,AES2=0x0,AES3=0x2"; + + if (mode == 8) { + gettimeofday(&start_time, NULL); + printf("bogus iec958 open\n"); + do { + err = snd_pcm_open(&this->audio_fd, pcm_dig, direction, open_mode); + gettimeofday(&end_time, NULL); + if( err == -EBUSY ) { + if( (double)end_time.tv_sec + 1E-6*end_time.tv_usec + - (double)start_time.tv_sec - 1E-6*start_time.tv_usec > 0.8) + break; + else + usleep(10000); + } + } while( err == -EBUSY ); + + if(err <0 ) { + xprintf (this->class->xine, XINE_VERBOSITY_LOG, + _("audio_alsa_out: snd_pcm_open() of %s failed: %s\n"), pcm_device, snd_strerror(err)); + xprintf (this->class->xine, XINE_VERBOSITY_LOG, + _("audio_alsa_out: >>> check if another program already uses PCM <<<\n")); + return 0; + } + snd_pcm_close (this->audio_fd); + printf("bogus iec958 close"); + } + gettimeofday(&start_time, NULL); do { err = snd_pcm_open(&this->audio_fd, pcm_device, direction, open_mode); @@ -380,7 +413,7 @@ static int ao_alsa_open(ao_driver_t *thi _("audio_alsa_out: >>> check if another program already uses PCM <<<\n")); return 0; } - /* printf ("audio_alsa_out: snd_pcm_open() opened %s\n", pcm_device); */ + printf ("audio_alsa_out: snd_pcm_open() opened %s\n", pcm_device); /* We wanted non blocking open but now put it back to normal */ //snd_pcm_nonblock(this->audio_fd, 0); snd_pcm_nonblock(this->audio_fd, 1); @@ -1364,7 +1397,7 @@ static ao_driver_t *open_plugin (audio_d this->mmap = config->register_bool (config, "audio.device.alsa_mmap_enable", - 0, + 1, _("sound card can do mmap"), _("Enable this, if your sound card and alsa driver " "support memory mapped IO.\nYou can try enabling it " @@ -1383,7 +1416,7 @@ static ao_driver_t *open_plugin (audio_d NULL); pcm_device = config->register_string(config, "audio.device.alsa_front_device", - "plug:front:default", + "default", _("device used for stereo output"), _("xine will use this alsa device to output " "stereo sound.\nSee the alsa documentation " @@ -1592,7 +1625,7 @@ static ao_driver_t *open_plugin (audio_d this->mixer.name = config->register_string(config, "audio.device.alsa_mixer_name", - "PCM", + "Front", _("alsa mixer device"), _("xine will use this alsa mixer device to change " "the volume.\nSee the alsa documentation for " diff -Naurpb xine-lib-1.2-04-19-08.org/src/combined/ffmpeg/ff_audio_decoder.c xine-lib-1.2-04.19.08/src/combined/ffmpeg/ff_audio_decoder.c --- xine-lib-1.2-04-19-08.org/src/combined/ffmpeg/ff_audio_decoder.c 2008-04-19 18:58:32.663793000 -0400 +++ xine-lib-1.2-04.19.08/src/combined/ffmpeg/ff_audio_decoder.c 2008-10-04 09:52:49.922994000 -0400 @@ -269,7 +269,7 @@ static void ff_audio_decode_data (audio_ * bits/sample for some codecs (e.g. MS ADPCM) */ this->audio_bits = 16; - this->context->bits_per_sample = this->audio_bits; + this->context->bits_per_coded_sample = this->audio_bits; this->context->sample_rate = this->audio_sample_rate; this->context->channels = this->audio_channels; this->context->codec_id = this->codec->id; @@ -322,12 +322,12 @@ static void ff_audio_decode_data (audio_ if (!this->output_open) { if (!this->audio_bits || !this->audio_sample_rate || !this->audio_channels) { - avcodec_decode_audio (this->context, + avcodec_decode_audio2 (this->context, (int16_t *)this->decode_buffer, &decode_buffer_size, &this->buf[0], this->size); - this->audio_bits = this->context->bits_per_sample; + this->audio_bits = this->context->bits_per_coded_sample; this->audio_sample_rate = this->context->sample_rate; this->audio_channels = this->context->channels; if (!this->audio_bits || !this->audio_sample_rate || !this->audio_channels) diff -Naurpb xine-lib-1.2-04-19-08.org/src/combined/ffmpeg/ff_video_decoder.c xine-lib-1.2-04.19.08/src/combined/ffmpeg/ff_video_decoder.c --- xine-lib-1.2-04-19-08.org/src/combined/ffmpeg/ff_video_decoder.c 2008-04-19 18:58:32.668794000 -0400 +++ xine-lib-1.2-04.19.08/src/combined/ffmpeg/ff_video_decoder.c 2008-10-04 09:45:46.549243000 -0400 @@ -385,9 +385,10 @@ static void init_video_codec (ff_video_d if (this->class->choose_speed_over_accuracy) this->context->flags2 |= CODEC_FLAG2_FAST; - + int error_code; pthread_mutex_lock(&ffmpeg_lock); - if (avcodec_open (this->context, this->codec) < 0) { + if (error_code = avcodec_open (this->context, this->codec) < 0) { + lprintf("failed to open codec %d, error code = %d\n",this->codec, error_code); pthread_mutex_unlock(&ffmpeg_lock); xprintf (this->stream->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: couldn't open decoder\n")); @@ -931,7 +932,7 @@ static void ff_handle_header_buffer (ff_ this->context->extradata_size); } - this->context->bits_per_sample = this->bih.biBitCount; + this->context->bits_per_coded_sample = this->bih.biBitCount; } else { @@ -1350,7 +1351,6 @@ static void ff_handle_buffer (ff_video_d /* colorspace conversion or copy */ ff_convert_frame(this, img); } - img->pts = this->pts; this->pts = 0; @@ -1800,9 +1800,10 @@ static const uint32_t supported_video_ty #if defined(HAVE_FFMPEG) || CONFIG_QTRLE_DECODER BUF_VIDEO_QTRLE, #endif -#if defined(HAVE_FFMPEG) || CONFIG_H264_DECODER +/*#if defined(HAVE_FFMPEG) || CONFIG_H264_DECODER BUF_VIDEO_H264, #endif +*/ #if defined(HAVE_FFMPEG) || CONFIG_H261_DECODER BUF_VIDEO_H261, #endif diff -Naurpb xine-lib-1.2-04-19-08.org/src/demuxers/bitstream.h xine-lib-1.2-04.19.08/src/demuxers/bitstream.h --- xine-lib-1.2-04-19-08.org/src/demuxers/bitstream.h 1969-12-31 19:00:00.000000000 -0500 +++ xine-lib-1.2-04.19.08/src/demuxers/bitstream.h 2008-04-19 18:47:35.638601000 -0400 @@ -0,0 +1,176 @@ +/* + * bitstream.h: generic bitstream parsing + * + * Re-produced from xinelibout + * + * $Id: bitstream.h,v 1.2 2008/02/04 22:41:14 phintuka Exp $ + * + */ + +#ifndef _XINELIBOUTPUT_BITSTREAM_H_ +#define _XINELIBOUTPUT_BITSTREAM_H_ + +#include + + +# ifdef NOCACHE + +typedef struct { + const uint8_t *data; + int count; /* in bits */ + int index; /* in bits */ +} br_state; + +#define BR_INIT(data,bytes) { (data), 8*(bytes), 0 } + +#define BR_EOF(br) ((br)->index >= (br)->count) + +static inline void br_init(br_state *br, const uint8_t *data, int bytes) +{ + br->data = data; + br->count = 8*bytes; + br->index = 0; +} + +static inline int br_get_bit(br_state *br) +{ + if(br->index >= br->count) + return 1; /* -> no infinite colomb's ... */ + + int r = (br->data[br->index>>3] >> (7 - (br->index&7))) & 1; + br->index++; + return r; +} + +static inline uint32_t br_get_bits(br_state *br, uint32_t n) +{ + uint32_t r = 0; + while(n--) + r = r | (br_get_bit(br) << n); + return r; +} + +#define br_skip_bit(br) br_skip_bits(br,1) + +static inline void br_skip_bits(br_state *br, int n) +{ + br->index += n; +} + + +# else /* NOCACHE */ + + +typedef struct { + uint8_t *data; + uint8_t *data_end; + uint32_t cache; + uint32_t cache_bits; +} br_state; + +#define BR_INIT(data,bytes) { (data), (data)+(bytes), 0, 0 } + +static inline void br_init(br_state *br, const uint8_t *data, int bytes) +{ + br->data = data; + br->data_end = data + bytes; + br->cache = 0; + br->cache_bits = 0; +} + +#define BR_GET_BYTE(br) \ + (br->data < br->data_end ? *br->data++ : 0xff) + +#define BR_EOF(br) ((br)->data >= (br)->data_end) + +static inline uint32_t br_get_bits(br_state *br, uint32_t n) +{ + if(n > 24) + return (br_get_bits(br, 16) << 16) | br_get_bits(br, n-16); + + while (br->cache_bits < 24) { + br->cache = (br->cache<<8) | BR_GET_BYTE(br); + br->cache_bits += 8; + } + + br->cache_bits -= n; + return (br->cache >> br->cache_bits) & ((1<cache_bits) { + br->cache = BR_GET_BYTE(br); + br->cache_bits = 7; + } else { + br->cache_bits--; + } + return (br->cache >> br->cache_bits) & 1; +} + +static inline void br_skip_bit(br_state *br) +{ + if(!br->cache_bits) { + br->cache = BR_GET_BYTE(br); + br->cache_bits = 7; + } else { + br->cache_bits--; + } +} + +static inline void br_skip_bits(br_state *br, int n) +{ + if(br->cache_bits >= n) { + br->cache_bits -= n; + } else { + /* drop cached bits */ + n -= br->cache_bits; + + /* drop full bytes */ + br->data += (n >> 3); + n &= 7; + + /* update cache */ + if(n) { + br->cache = BR_GET_BYTE(br); + br->cache_bits = 8 - n; + } else { + br->cache_bits = 0; + } + } +} + + +# endif /* NOCACHE */ + + +#define br_get_u8(br) br_get_bits(br, 8) +#define br_get_u16(br) ((br_get_bits(br, 8)<<8) | br_get_bits(br, 8)) + +static inline uint32_t br_get_ue_golomb(br_state *br) +{ + int n = 0; + while (!br_get_bit(br) && n < 32) + n++; + return n ? ((1<>1) : (r>>1); +} + +static inline void br_skip_golomb(br_state *br) +{ + int n = 0; + while (!br_get_bit(br) && n < 32) + n++; + br_skip_bits(br, n); +} + +#define br_skip_ue_golomb(br) br_skip_golomb(br) +#define br_skip_se_golomb(br) br_skip_golomb(br) + + +#endif /* _XINELIBOUTPUT_BITSTREAM_H_ */ diff -Naurpb xine-lib-1.2-04-19-08.org/src/demuxers/demux_mpeg.c xine-lib-1.2-04.19.08/src/demuxers/demux_mpeg.c --- xine-lib-1.2-04-19-08.org/src/demuxers/demux_mpeg.c 2008-04-19 18:58:32.835806000 -0400 +++ xine-lib-1.2-04.19.08/src/demuxers/demux_mpeg.c 2008-04-19 18:47:35.638601000 -0400 @@ -536,6 +536,74 @@ static void parse_mpeg2_packet (demux_mp this->video_fifo->put (this->video_fifo, buf); } + } else if (stream_id == 0xfd) { + + w = read_bytes(this, 1); + flags = read_bytes(this, 1); + header_len = read_bytes(this, 1); + + len -= header_len + 3; + + pts = 0; + dts = 0; + + if ((flags & 0x80) == 0x80) { + + w = read_bytes(this, 1); + pts = (int64_t)(w & 0x0e) << 29 ; + w = read_bytes(this, 2); + pts |= (w & 0xFFFE) << 14; + w = read_bytes(this, 2); + pts |= (w & 0xFFFE) >> 1; + + header_len -= 5 ; + } + + if ((flags & 0x40) == 0x40) { + + w = read_bytes(this, 1); + dts = (int64_t)(w & 0x0e) << 29 ; + w = read_bytes(this, 2); + dts |= (w & 0xFFFE) << 14; + w = read_bytes(this, 2); + dts |= (w & 0xFFFE) >> 1; + + header_len -= 5 ; + } + + /* read rest of header */ + i = this->input->read (this->input, this->dummy_space, header_len); + + /* contents */ + + for (i = len; i > 0; i -= this->video_fifo->buffer_pool_buf_size) { + buf = this->input->read_block (this->input, this->video_fifo, + (i > this->video_fifo->buffer_pool_buf_size) ? this->video_fifo->buffer_pool_buf_size : i); + + if (buf == NULL) { + this->status = DEMUX_FINISHED; + return; + } + + buf->type = BUF_VIDEO_VC1; + buf->pts = pts; + buf->decoder_info[0] = pts - dts; + check_newpts( this, pts, PTS_VIDEO ); + pts = 0; + + if (this->preview_mode) + buf->decoder_flags = BUF_FLAG_PREVIEW; + + if( this->input->get_length (this->input) ) + buf->extra_info->input_normpos = + (int)( ((int64_t)this->input->get_current_pos (this->input) * + 65535) / this->input->get_length (this->input) ); + if (this->rate) + buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) + * 1000 / (this->rate * 50)); + + this->video_fifo->put (this->video_fifo, buf); + } } else { for (i = len; i > 0; i -= 10000) diff -Naurpb xine-lib-1.2-04-19-08.org/src/demuxers/demux_mpeg_pes.c xine-lib-1.2-04.19.08/src/demuxers/demux_mpeg_pes.c --- xine-lib-1.2-04-19-08.org/src/demuxers/demux_mpeg_pes.c 2008-04-19 18:58:32.853807000 -0400 +++ xine-lib-1.2-04.19.08/src/demuxers/demux_mpeg_pes.c 2008-05-28 10:02:03.749609000 -0400 @@ -34,6 +34,7 @@ #include #include #include +#include "bitstream.h" #define LOG_MODULE "demux_mpeg_pes" #define LOG_VERBOSE @@ -110,6 +111,37 @@ typedef struct { config_values_t *config; } demux_mpeg_pes_class_t; +typedef struct { + int width; + int height; + double ratio; + /* ... */ +} h264_sps_data_t; + +typedef struct AVRational{ + int num; ///< numerator + int den; ///< denominator +} AVRational; + +static const AVRational pixel_aspect[16]={ + {0, 1}, + {1, 1}, + {12, 11}, + {10, 11}, + {16, 11}, + {40, 33}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {15, 11}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, +}; + static int32_t parse_video_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf); static int32_t parse_audio_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf); static int32_t parse_ancillary_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf); @@ -132,6 +164,7 @@ static int32_t parse_IEC14496_SL_packeti static int32_t parse_IEC14496_FlexMux_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf); static int32_t parse_program_stream_directory(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf); static int32_t parse_program_stream_pack_header(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf); +int h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps); static int detect_pts_discontinuity( demux_mpeg_pes_t *this, int64_t pts, int video ) { @@ -210,7 +243,7 @@ static void check_newpts( demux_mpeg_pes /* check if pts is outside nav pts range. any stream without nav must enter here. */ if( pts > this->nav_last_end_pts || pts < this->nav_last_start_pts ) { - lprintf("discontinuity detected by pts wrap\n"); + printf("discontinuity detected by pts wrap\n"); if (this->buf_flag_seek) { _x_demux_control_newpts(this->stream, pts, BUF_FLAG_SEEK); @@ -220,7 +253,7 @@ static void check_newpts( demux_mpeg_pes } this->send_newpts = 0; } else { - lprintf("no wrap detected\n" ); + printf("no wrap detected\n" ); } /* clear pts on the other track to avoid detecting the same discontinuity again */ @@ -607,7 +640,7 @@ static int32_t parse_program_stream_pack this->scr += ( (p[8] & 0x03 << 7) | (p[9] & 0xFE >> 1) ); */ - lprintf ("SCR=%"PRId64"\n", this->scr); + printf ("SCR=%"PRId64"\n", this->scr); /* mux_rate */ @@ -846,10 +879,10 @@ static int32_t parse_pes_for_pts(demux_m } else this->dts = 0; - header_len = p[8]; this->packet_len -= header_len + 3; + lprintf("pts = %"PRId64", dts = %"PRId64"\n", this->pts, this->dts); return header_len + 9; } return 0; @@ -939,7 +972,7 @@ static int32_t parse_private_stream_1(de if(this->audio_fifo) { this->audio_fifo->put (this->audio_fifo, buf); - lprintf ("A52 PACK put on fifo\n"); + lprintf ("A52 PACK put on fifo, Audio pts=%"PRId64"\n",this->pts); } else { buf->free_buffer(buf); @@ -1092,6 +1125,143 @@ static int32_t parse_private_stream_1(de return this->packet_len + result; } +int h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps) +{ + br_state br = BR_INIT(buf, len); + int profile_idc, pic_order_cnt_type; + int frame_mbs_only; + int i, j; + + profile_idc = br_get_u8(&br); + printf("H.264 SPS: profile_idc %d\n", profile_idc); + /* constraint_set0_flag = br_get_bit(br); */ + /* constraint_set1_flag = br_get_bit(br); */ + /* constraint_set2_flag = br_get_bit(br); */ + /* constraint_set3_flag = br_get_bit(br); */ + /* reserved = br_get_bits(br,4); */ + /* level_idc = br_get_u8(br); */ + br_skip_bits(&br, 16); + br_skip_ue_golomb(&br); /* seq_parameter_set_id */ + if (profile_idc >= 100) { + if (br_get_ue_golomb(&br) == 3) /* chroma_format_idc */ + br_skip_bit(&br); /* residual_colour_transform_flag */ + br_skip_ue_golomb(&br); /* bit_depth_luma - 8 */ + br_skip_ue_golomb(&br); /* bit_depth_chroma - 8 */ + br_skip_bit(&br); /* transform_bypass */ + if (br_get_bit(&br)) /* seq_scaling_matrix_present */ + for (i = 0; i < 8; i++) + if (br_get_bit(&br)) { /* seq_scaling_list_present */ + int last = 8, next = 8, size = (i<6) ? 16 : 64; + for (j = 0; j < size; j++) { + if (next) + next = (last + br_get_se_golomb(&br)) & 0xff; + last = next ?: last; + } + } + } + + br_skip_ue_golomb(&br); /* log2_max_frame_num - 4 */ + pic_order_cnt_type = br_get_ue_golomb(&br); + if (pic_order_cnt_type == 0) + br_skip_ue_golomb(&br); /* log2_max_poc_lsb - 4 */ + else if (pic_order_cnt_type == 1) { + br_skip_bit(&br); /* delta_pic_order_always_zero */ + br_skip_se_golomb(&br); /* offset_for_non_ref_pic */ + br_skip_se_golomb(&br); /* offset_for_top_to_bottom_field */ + j = br_get_ue_golomb(&br); /* num_ref_frames_in_pic_order_cnt_cycle */ + for (i = 0; i < j; i++) + br_skip_se_golomb(&br); /* offset_for_ref_frame[i] */ + } + br_skip_ue_golomb(&br); /* ref_frames */ + br_skip_bit(&br); /* gaps_in_frame_num_allowed */ + sps->width /* mbs */ = br_get_ue_golomb(&br) + 1; + sps->height /* mbs */ = br_get_ue_golomb(&br) + 1; + frame_mbs_only = br_get_bit(&br); + printf("H.264 SPS: pic_width: %u mbs\n", (unsigned) sps->width); + printf("H.264 SPS: pic_height: %u mbs\n", (unsigned) sps->height); + printf("H.264 SPS: frame only flag: %d\n", frame_mbs_only); + + sps->width *= 16; + sps->height *= 16 * (2-frame_mbs_only); + + if (!frame_mbs_only) + if (br_get_bit(&br)) /* mb_adaptive_frame_field_flag */ + printf("H.264 SPS: MBAFF\n"); + br_skip_bit(&br); /* direct_8x8_inference_flag */ + if (br_get_bit(&br)) { /* frame_cropping_flag */ + uint32_t crop_left = br_get_ue_golomb(&br); + uint32_t crop_right = br_get_ue_golomb(&br); + uint32_t crop_top = br_get_ue_golomb(&br); + uint32_t crop_bottom = br_get_ue_golomb(&br); + printf("H.264 SPS: cropping %d %d %d %d\n", + crop_left, crop_top, crop_right, crop_bottom); + + sps->width -= 2*(crop_left + crop_right); + if (frame_mbs_only) + sps->height -= 2*(crop_top + crop_bottom); + else + sps->height -= 4*(crop_top + crop_bottom); + } + + printf("H.264 SPS: -> video size %dx%d \n", sps->width, sps->height); + + if (br_get_bit(&br)) { /* VUI parameters */ + if (br_get_bit(&br)) { /* Aspect Info */ + uint32_t aspect_ratio_idc = br_get_u8(&br); + printf("H.264 SPS: -> Aspect Ratio IDC %d\n", aspect_ratio_idc); + const uint32_t Extended_SAR = 255; + if (aspect_ratio_idc == Extended_SAR) { + uint32_t sar_width = br_get_u16(&br); + uint32_t sar_height = br_get_u16(&br); + sps->ratio = (float) sar_width / sar_height; + sps->ratio = (float) ( (float) sar_width / sar_height ) * ( (float) sps->width / sps->height ) ; + printf("H.264 SPS: -> SAR_Size = %dx%d\n", sar_width, sar_height); + printf("H.264 SPS: -> Ratio = %f\n", sps->ratio); + } else { + AVRational sar = pixel_aspect[aspect_ratio_idc]; + printf("H.264 SPS: -> Pixel Aspect = %d / %d\n", sar.num, sar.den); + sps->ratio = (float) ( (float) sar.num / sar.den ) * ( (float) sps->width / sps->height ) ; + printf("H.264 SPS: -> Ratio = %f\n", sps->ratio); + } + } + } + + + if(BR_EOF(&br)) { + printf("H.264 SPS: not enough data ?\n"); + return 0; + } + return 1; +} + +static int h264_nal_unescape(uint8_t *dst, const uint8_t *src, int len) +{ + int s = 0, d = 0; + while (s < len) { + if (!src[s] && !src[s+1]) { + /* hit 00 00 xx */ + dst[d] = dst[d+1] = 0; + s += 2; + d += 2; + if (src[s] == 3) { + s++; /* 00 00 03 xx --> 00 00 xx */ + /*printf("h264_nal_unescape: hit 00 00 03 %02x", src[s]);*/ + if (s >= len) + return d; + } /* else if (src[s] == 0 || src[s] == 1) { + printf("h264_nal_unescape: invalid NAL sequence 00 00 %02x %02x\n", src[s], src[s+1]); + return -1; + }*/ + } + dst[d++] = src[s++]; + } + return d; +} + +int sent_header = 0; /* Added by Mel */ +int found_iframe = 0; +h264_sps_data_t sps = {0}; + static int32_t parse_video_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { int32_t result; uint32_t todo_length=0; @@ -1136,6 +1306,7 @@ static int32_t parse_video_stream(demux_ an AUD has been found at the beginning of the payload. */ if (this->mpeg12_h264_detected < 2) { + sent_header = 0; /* Added by Mel */ uint8_t *pp = p + 2, *pp_limit = p + payload_size - 1; while (0 < pp && pp < pp_limit) { if (pp[0] == 0x01 && pp[-1] == 0x00 && pp[-2] == 0x00) { @@ -1144,7 +1315,7 @@ static int32_t parse_video_stream(demux_ break; } else { int nal_type_code = pp[1] & 0x1f; - if (nal_type_code == 9 && pp == (p + 2)) { /* access unit delimiter */ + if ( (nal_type_code == 9) && (pp == (p + 2)) && (found_iframe == 1)) { /* access unit delimiter */ if (this->mpeg12_h264_detected == 1) { this->mpeg12_h264_detected = 3; break; @@ -1156,8 +1327,70 @@ static int32_t parse_video_stream(demux_ pp++; pp = memchr(pp, 0x01, pp_limit - pp); } + + usleep(100); /* Added by Mel */ lprintf("%s%c\n", (this->mpeg12_h264_detected & 1) ? "H.264" : "MPEG1/2", (this->mpeg12_h264_detected & 2) ? '!' : '?'); + +if ((found_iframe == 0) && (this->mpeg12_h264_detected != 2)) { + int primary_pic_type = p[4] >> 5; + if ( (p[0] == 0x00) && (p[1] == 0x00) & (p[2] == 0x01) ) + { + if ( (primary_pic_type == 0x00) || (primary_pic_type == 0x03) || (primary_pic_type == 0x05) ) { + printf ("FOUND IFRAME!\n "); + int i = 0; + for (i = 5; i < payload_size-4; i++) { + //printf("%d %d %d %d\n", p[i], p[i+1], p[i+2], p[i+3] & 0x1f); + if (p[i] == 0x00 && p[i+1] == 0x00 && p[i+2] == 0x01 && (p[i+3] & 0x1f) == 0x07) { + printf("FOUND NAL SPS at %d!\n", i); + uint8_t nal_data[payload_size]; + int nal_len; + if (0 < (nal_len = h264_nal_unescape(nal_data, p+i+4, payload_size-i-4))) { + if ( h264_parse_sps(nal_data, nal_len, &sps) ) { + found_iframe = 1; + break; + } } + } + } + } + } +} + + if (this->mpeg12_h264_detected == 3 ) { + if (sent_header == 0 ) { + //xine_set_param(this->stream, XINE_PARAM_VO_DEINTERLACE,0); + printf("INIT H264\n"); + xine_bmiheader bih; + buf_element_t *buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->decoder_flags = BUF_FLAG_STDHEADER; + + xine_fast_memset(&bih, 0x00, sizeof(bih)); + bih.biWidth = sps.width; + bih.biHeight = sps.height; + bih.biPlanes = 1; + bih.biBitCount = 24; + bih.biCompression = 0x34363248; //31435641; //AVC1 + bih.biSizeImage = 0; + bih.biXPelsPerMeter=0; + bih.biYPelsPerMeter=0; + bih.biClrUsed=0; + bih.biClrImportant=0; + bih.biSize = sizeof(bih); + buf->content = malloc(sizeof(bih)); + memcpy(buf->content, &bih, sizeof(bih)); + //memcpy(buf->content, &bih, sizeof(bih)); + buf->size = sizeof(bih); + buf->type = BUF_VIDEO_H264; + buf->decoder_flags |= BUF_FLAG_FRAME_END; + this->video_fifo->put (this->video_fifo, buf); + sent_header = 1; + found_iframe = 0; + buf = NULL; + } + } +} + +// Mel END /* when an H.264 AUD is seen, we first need to tell the decoder that the previous frame was complete. @@ -1259,7 +1492,7 @@ static int32_t parse_audio_stream(demux_ if(this->audio_fifo) { this->audio_fifo->put (this->audio_fifo, buf); - lprintf ("MPEG Audio PACK put on fifo\n"); + lprintf ("MPEG Audio PACK put on fifo, Audio PTS=%"PRId64"\n",this->pts); } else { buf->free_buffer(buf); } diff -Naurpb xine-lib-1.2-04-19-08.org/src/demuxers/demux_qt.c xine-lib-1.2-04.19.08/src/demuxers/demux_qt.c --- xine-lib-1.2-04-19-08.org/src/demuxers/demux_qt.c 2008-04-19 18:58:32.890810000 -0400 +++ xine-lib-1.2-04.19.08/src/demuxers/demux_qt.c 2008-04-19 18:47:35.641601000 -0400 @@ -2760,13 +2760,6 @@ static void demux_qt_send_headers(demux_ /* send init info to decoders */ if (video_trak && (video_trak->properties->video.codec_buftype)) { - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; - - memcpy(buf->content, &this->bih, sizeof(this->bih)); - buf->size = sizeof(this->bih); - buf->type = video_trak->properties->video.codec_buftype; - this->video_fifo->put (this->video_fifo, buf); /* send header info to decoder. some mpeg4 streams need this */ if( video_trak->decoder_config ) { @@ -2787,6 +2780,14 @@ static void demux_qt_send_headers(demux_ this->video_fifo->put (this->video_fifo, buf); } + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; + + memcpy(buf->content, &this->bih, sizeof(this->bih)); + buf->size = sizeof(this->bih); + buf->type = video_trak->properties->video.codec_buftype; + this->video_fifo->put (this->video_fifo, buf); + /* send off the palette, if there is one */ if (video_trak->properties->video.palette_count) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); diff -Naurpb xine-lib-1.2-04-19-08.org/src/demuxers/demux_ts.c xine-lib-1.2-04.19.08/src/demuxers/demux_ts.c --- xine-lib-1.2-04-19-08.org/src/demuxers/demux_ts.c 2008-04-19 18:58:32.955815000 -0400 +++ xine-lib-1.2-04.19.08/src/demuxers/demux_ts.c 2008-04-19 18:47:35.642601000 -0400 @@ -220,7 +220,8 @@ ISO_13818_PART7_AUDIO = 0x0f, /* ISO/IEC 13818-7 Audio with ADTS transport sytax */ ISO_14496_PART2_VIDEO = 0x10, /* ISO/IEC 14496-2 Visual (MPEG-4) */ ISO_14496_PART3_AUDIO = 0x11, /* ISO/IEC 14496-3 Audio with LATM transport syntax */ - ISO_14496_PART10_VIDEO = 0x1b /* ISO/IEC 14496-10 Video (MPEG-4 part 10/AVC, aka H.264) */ + ISO_14496_PART10_VIDEO = 0x1b, /* ISO/IEC 14496-10 Video (MPEG-4 part 10/AVC, aka H.264) */ + STREAMDEV_H264_VIDEO = 0xe0 /* ISO/IEC 14496-10 Video (MPEG-4 part 10/AVC, aka H.264) */ } streamType; #define WRAP_THRESHOLD 270000 @@ -250,6 +251,7 @@ typedef struct { int64_t packet_count; int corrupted_pes; uint32_t buffered_bytes; + unsigned int sent_headers; } demux_ts_media; @@ -717,7 +719,7 @@ static int demux_ts_parse_pes_header (xi p += header_len + 9; packet_len -= header_len + 3; - if (stream_id == 0xbd) { + if (stream_id == PRIVATE_STREAM1) { int spu_id; @@ -791,6 +793,7 @@ static int demux_ts_parse_pes_header (xi lprintf ("demux_ts: found MPEG4 video type.\n"); m->type = BUF_VIDEO_MPEG4; break; + case STREAMDEV_H264_VIDEO: case ISO_14496_PART10_VIDEO: lprintf ("demux_ts: found H264 video type.\n"); m->type = BUF_VIDEO_H264; @@ -884,6 +887,43 @@ static void demux_ts_buffer_pes(demux_ts else m->buf->decoder_flags=BUF_FLAG_FRAME_END; } + + /* hack for win32 codecs, because w32codec.c always + waits for BUF_FLAG_FRAME_END before passing to the decoder. + At least for coreavc this is not necessary, because it does + depacketizing itself */ + if(m->buf->type == BUF_VIDEO_H264) { + m->buf->decoder_flags |= BUF_FLAG_FRAME_END; + if(!m->sent_headers) { + /* HACK FOR COREAVC */ + printf("INIT H264\n"); + xine_bmiheader bih; + buf_element_t *buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->decoder_flags = BUF_FLAG_STDHEADER; + + memset(&bih, 0x00, sizeof(bih)); + bih.biWidth = 1920; + bih.biHeight = 1080; + bih.biPlanes = 1; + bih.biBitCount = 24; + bih.biCompression = 0x34363248; //31435641; //AVC1 + bih.biSizeImage = 0; + bih.biXPelsPerMeter=10000; + bih.biYPelsPerMeter=10000; + bih.biClrUsed=0; + bih.biClrImportant=0; + bih.biSize = sizeof(bih); + buf->content = malloc(sizeof(bih)); + memcpy(buf->content, &bih, sizeof(bih)); + //memcpy(buf->content, &bih, sizeof(bih)); + buf->size = sizeof(bih); + buf->type = BUF_VIDEO_H264; + this->video_fifo->put (this->video_fifo, buf); + buf = NULL; + m->sent_headers = 1; + } + } + m->buf->pts = m->pts; m->buf->decoder_info[0] = 1; @@ -917,6 +957,13 @@ static void demux_ts_buffer_pes(demux_ts } } else { + if(m->corrupted_pes) { + buf_element_t *buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); + buf->type = BUF_VIDEO_H264; + buf->pts = 0; + this->video_fifo->put(this->video_fifo, buf); + } + m->corrupted_pes = 0; memcpy(m->buf->mem, ts+len-m->size, m->size); m->buffered_bytes = m->size; @@ -972,6 +1019,7 @@ static void demux_ts_pes_new(demux_ts_t* m->descriptor_tag = descriptor; m->corrupted_pes = 1; m->buffered_bytes = 0; + m->sent_headers = 0; } @@ -1804,6 +1852,9 @@ static void demux_ts_parse_packet (demux printf("demux_ts:ts_pes_header:stream_id=0x%.2x\n",pes_stream_id); #endif + if ((this->videoPid != INVALID_PID) && (this->videoPid != pid) && (pes_stream_id == STREAMDEV_H264_VIDEO)) + this->videoPid = INVALID_PID; + if ( (pes_stream_id >= VIDEO_STREAM_S) && (pes_stream_id <= VIDEO_STREAM_E) ) { if ( this->videoPid == INVALID_PID) { int i, found = 0; @@ -1828,7 +1879,7 @@ static void demux_ts_parse_packet (demux "demux_ts: auto-detected video pid 0x%.4x\n", pid); } } - } else if ( (pes_stream_id >= AUDIO_STREAM_S) && (pes_stream_id <= AUDIO_STREAM_E) ) { + } else if ( (pes_stream_id >= AUDIO_STREAM_S) && (pes_stream_id <= AUDIO_STREAM_E) || (pes_stream_id == PRIVATE_STREAM1) ) { if (this->audio_tracks_count < MAX_AUDIO_TRACKS) { int i, found = 0; for(i = 0; i < this->audio_tracks_count; i++) { diff -Naurpb xine-lib-1.2-04-19-08.org/src/input/input_v4l.c xine-lib-1.2-04.19.08/src/input/input_v4l.c --- xine-lib-1.2-04-19-08.org/src/input/input_v4l.c 2008-04-19 18:58:33.170831000 -0400 +++ xine-lib-1.2-04.19.08/src/input/input_v4l.c 2008-05-07 09:59:22.395544000 -0400 @@ -1930,7 +1930,7 @@ static void *init_video_class (xine_t *x _("The path to your Video4Linux video device."), 10, NULL, NULL); - config->register_enum (config, "media.video4linux.tv_standard", 0, + config->register_enum (config, "media.video4linux.tv_standard", 1, tv_standard_names, _("v4l TV standard"), _("Selects the TV standard of the input signals. " "Either: PAL, NTSC and SECAM. "), 20, NULL, NULL); diff -Naurpb xine-lib-1.2-04-19-08.org/src/libw32dll/common.c xine-lib-1.2-04.19.08/src/libw32dll/common.c --- xine-lib-1.2-04-19-08.org/src/libw32dll/common.c 2008-04-19 18:58:33.922886000 -0400 +++ xine-lib-1.2-04.19.08/src/libw32dll/common.c 2008-05-07 10:00:49.648057000 -0400 @@ -6,14 +6,14 @@ static char *get_win32_codecs_path(confi DIR *dir; char *path, *cfgpath; char *listpath[] = { "", + "/usr/local/lib/win32", "/usr/lib/codecs", "/usr/local/lib/codecs", "/usr/lib/win32", - "/usr/local/lib/win32", NULL }; int i = 0; - cfgpath = cfg->register_filename (cfg, "decoder.external.win32_codecs_path", WIN32_PATH, XINE_CONFIG_STRING_IS_DIRECTORY_NAME, + cfgpath = cfg->register_filename (cfg, "decoder.external.win32_codecs_path", "/usr/local/lib/win32", XINE_CONFIG_STRING_IS_DIRECTORY_NAME, _("path to Win32 codecs"), _("If you have the Windows or Apple Quicktime codec packs " "installed, specify the path the codec directory here. " diff -Naurpb xine-lib-1.2-04-19-08.org/src/post/deinterlace/xine_plugin.c xine-lib-1.2-04.19.08/src/post/deinterlace/xine_plugin.c --- xine-lib-1.2-04-19-08.org/src/post/deinterlace/xine_plugin.c 2008-04-19 18:58:34.066897000 -0400 +++ xine-lib-1.2-04.19.08/src/post/deinterlace/xine_plugin.c 2008-07-07 17:19:23.901354000 -0400 @@ -122,6 +122,8 @@ struct post_plugin_deinterlace_s { int tvtime_changed; int tvtime_last_filmmode; int vo_deinterlace_enabled; + const char *video_codec; + int h264_stream; int framecounter; uint8_t rff_pattern; @@ -476,6 +478,15 @@ static void deinterlace_open(xine_video_ post_video_port_t *port = (post_video_port_t *)port_gen; post_plugin_deinterlace_t *this = (post_plugin_deinterlace_t *)port->post; + this->video_codec = _x_meta_info_get(stream,XINE_META_INFO_VIDEOCODEC); + lprintf("deinterlace_open: video codec=%s\n",this->video_codec); + if (this->video_codec != NULL) { + if (strcmp(this->video_codec,"H264 (libcoreavc)") == 0) + this->h264_stream = 1; + else + this->h264_stream = 0; + } + _x_post_rewire(&this->post); _x_post_inc_usage(port); port->stream = stream; @@ -509,7 +520,6 @@ static int deinterlace_intercept_frame(p vo_deinterlace_enabled = ( frame->format != XINE_IMGFMT_YV12 && frame->format != XINE_IMGFMT_YUY2 && this->enabled ); - if( this->cur_method && this->vo_deinterlace_enabled != vo_deinterlace_enabled ) { this->vo_deinterlace_enabled = vo_deinterlace_enabled; @@ -517,7 +527,6 @@ static int deinterlace_intercept_frame(p XINE_PARAM_VO_DEINTERLACE, this->vo_deinterlace_enabled); } - return (this->enabled && this->cur_method && (frame->flags & VO_INTERLACED_FLAG) && (frame->format == XINE_IMGFMT_YV12 || frame->format == XINE_IMGFMT_YUY2) ); @@ -552,6 +561,16 @@ static int deinterlace_build_output_fiel int scaler = 1; int force24fps; +// this->video_codec = _x_meta_info_get(stream,XINE_META_INFO_VIDEOCODEC); +// printf("Deinterlace Build Output Field\n"); + if (frame->width > 1280 && this->h264_stream) + this->cheap_mode=1; + else + if (frame->width > 1450) + this->cheap_mode=1; + else + this->cheap_mode=0; + force24fps = this->judder_correction && !this->cheap_mode && ( this->pulldown == PULLDOWN_VEKTOR && this->tvtime->filmmode ); @@ -659,7 +678,7 @@ static int deinterlace_build_output_fiel frame->width, frame->height / scaler ); skip = deinterlaced_frame->draw(deinterlaced_frame, stream); } - +// printf("deinterlaced frame pts=%"PRId64",deinterlaced frame duration=%d, force24fps=%d\n", deinterlaced_frame->pts, deinterlaced_frame->duration, force24fps); /* _x_post_frame_copy_up(frame, deinterlaced_frame); */ deinterlaced_frame->free(deinterlaced_frame); pthread_mutex_lock (&this->lock); @@ -764,7 +783,6 @@ static int deinterlace_draw(vo_frame_t * yuy2_frame->lock(yuy2_frame); } - pthread_mutex_lock (&this->lock); /* check if frame format changed */ for(i = 0; i < NUM_RECENT_FRAMES; i++ ) { @@ -842,8 +860,6 @@ static int deinterlace_draw(vo_frame_t * _x_post_frame_copy_up(frame, yuy2_frame); } else { - - /* If the previous field was progressive and we are using a * filter that delays it's output by one field then we need * to skip the first field's output. Otherwise the effective diff -Naurpb xine-lib-1.2-04-19-08.org/src/post/goom/xine_goom.c xine-lib-1.2-04.19.08/src/post/goom/xine_goom.c --- xine-lib-1.2-04-19-08.org/src/post/goom/xine_goom.c 2008-04-19 18:58:34.152903000 -0400 +++ xine-lib-1.2-04.19.08/src/post/goom/xine_goom.c 2008-04-24 18:44:47.415182000 -0400 @@ -44,8 +44,8 @@ #define NUMSAMPLES 512 /* hardcoded into goom api */ #define FPS 14 -#define GOOM_WIDTH 320 -#define GOOM_HEIGHT 240 +#define GOOM_WIDTH 640 +#define GOOM_HEIGHT 360 /* colorspace conversion methods */ static const char const * goom_csc_methods[]={ @@ -206,12 +206,12 @@ static void *goom_init_plugin(xine_t *xi "smoother and faster, but will also require more CPU power."), 10, fps_changed_cb, this); - cfg->register_num (cfg, "effects.goom.width", GOOM_WIDTH, + cfg->register_num (cfg, "effects.goom.width", 640, _("goom image width"), _("The width in pixels of the image to be generated."), 10, width_changed_cb, this); - cfg->register_num (cfg, "effects.goom.height", GOOM_HEIGHT, + cfg->register_num (cfg, "effects.goom.height", 360, _("goom image height"), _("The height in pixels of the image to be generated."), 10, height_changed_cb, this); diff -Naurpb xine-lib-1.2-04-19-08.org/src/vdr/input_vdr.c xine-lib-1.2-04.19.08/src/vdr/input_vdr.c --- xine-lib-1.2-04-19-08.org/src/vdr/input_vdr.c 2008-04-19 18:58:34.212907000 -0400 +++ xine-lib-1.2-04.19.08/src/vdr/input_vdr.c 2008-07-03 18:10:17.727598000 -0400 @@ -38,6 +38,7 @@ #define LOG_MODULE "input_vdr" #define LOG_VERBOSE +//#define LOG /* #define LOG */ @@ -121,6 +122,7 @@ struct vdr_input_plugin_s uint16_t image4_3_zoom_y; uint16_t image16_9_zoom_x; uint16_t image16_9_zoom_y; + xine_video_port_t *vo; uint8_t find_sync_point; pthread_mutex_t find_sync_point_lock; @@ -409,6 +411,18 @@ static off_t vdr_execute_rpc_command(vdr xine_osd_show(this->osd_window[ data->window ], 0); } } + + vdr_set_video_window_data_t event_data; + + event_data.x = 0; + event_data.y = 0; + event_data.w = 1; + event_data.h = 1; + event_data.w_ref = 1; + event_data.h_ref = 1; + this->stream->video_driver->gui_data_exchange(this->stream->video_driver, XINE_EVENT_VDR_SETVIDEOWINDOW, &event_data); +// xine_port_send_gui_data(this->stream->video_driver, XINE_EVENT_VDR_SETVIDEOWINDOW, &event_data); + break; case func_osd_flush: @@ -440,7 +454,7 @@ static off_t vdr_execute_rpc_command(vdr } _t2 = _now(); - fprintf(stderr, "vdr: osdflush: n: %d, %.1lf, timeout: %d, result: %d\n", _n, _t2 - _t1, _to, r); + lprintf("vdr: osdflush: n: %d, %.1lf, timeout: %d, result: %d\n", _n, _t2 - _t1, _to, r); /* fprintf(stderr, "redraw_needed: 0\n"); @@ -669,6 +683,8 @@ fprintf(stderr, "--- CLEAR(%d%c)\n", dat event.data = &event_data; event.data_length = sizeof (event_data); + this->stream->video_driver->gui_data_exchange(this->stream->video_driver, XINE_EVENT_VDR_SETVIDEOWINDOW, &event_data); +// xine_port_send_gui_data(this->stream->video_driver, XINE_EVENT_VDR_SETVIDEOWINDOW, &event_data); xine_event_send(this->stream, &event); } } diff -Naurpb xine-lib-1.2-04-19-08.org/src/video_dec/libmpeg2/decode.c xine-lib-1.2-04.19.08/src/video_dec/libmpeg2/decode.c --- xine-lib-1.2-04-19-08.org/src/video_dec/libmpeg2/decode.c 2008-04-19 18:58:34.222908000 -0400 +++ xine-lib-1.2-04.19.08/src/video_dec/libmpeg2/decode.c 2008-04-19 18:47:35.649602000 -0400 @@ -153,8 +153,18 @@ static inline void get_frame_duration (m } frame->duration = (int) ceil (duration); + if (frame->duration > 1900 && mpeg2dec->picture->frame_rate_code == 4) + frame->progressive_frame = 0; _x_stream_info_set(mpeg2dec->stream, XINE_STREAM_INFO_FRAME_DURATION, frame->duration); /*printf("mpeg2dec: rff=%u\n",frame->repeat_first_field);*/ + lprintf("***************************\n"); + lprintf("Frame Duration = %d\n",frame->duration); + lprintf("Progressive frame = %d\n",frame->progressive_frame); + lprintf("Top Field First = %d\n",frame->top_field_first); + lprintf("Repeat First Field = %d\n",frame->repeat_first_field); + lprintf("Frame Rate Code = %d\n",mpeg2dec->picture->frame_rate_code); + lprintf("Frame PTS = %"PRId64"\n",frame->pts); + lprintf("**************************\n"); } static double get_aspect_ratio(mpeg2dec_t *mpeg2dec) @@ -204,7 +214,7 @@ static void remember_metainfo (mpeg2dec_ _x_stream_info_set(mpeg2dec->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, picture->display_height); _x_stream_info_set(mpeg2dec->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000 * get_aspect_ratio(mpeg2dec))); - + lprintf("Frame Rate Code=%d\n",mpeg2dec->picture->frame_rate_code); switch (mpeg2dec->picture->frame_rate_code) { case 1: /* 23.976 fps */ _x_stream_info_set(mpeg2dec->stream, XINE_STREAM_INFO_FRAME_DURATION, 3913); @@ -715,7 +725,7 @@ int mpeg2_decode_data (mpeg2dec_t * mpeg if (pts) mpeg2dec->pts = pts; - while (current != end || mpeg2dec->code == 0xb7) { + while (current <= end || mpeg2dec->code == 0xb7) { code = mpeg2dec->code; current = copy_chunk (mpeg2dec, current, end); if (current == NULL) diff -Naurpb xine-lib-1.2-04-19-08.org/src/video_dec/libmpeg2/xine_mpeg2_decoder.c xine-lib-1.2-04.19.08/src/video_dec/libmpeg2/xine_mpeg2_decoder.c --- xine-lib-1.2-04-19-08.org/src/video_dec/libmpeg2/xine_mpeg2_decoder.c 2008-04-19 18:58:34.243910000 -0400 +++ xine-lib-1.2-04.19.08/src/video_dec/libmpeg2/xine_mpeg2_decoder.c 2008-04-19 18:47:35.650602000 -0400 @@ -39,6 +39,7 @@ #include "mpeg2.h" #include "mpeg2_internal.h" #include +#include typedef struct { video_decoder_class_t decoder_class; diff -Naurpb xine-lib-1.2-04-19-08.org/src/video_out/video_out_xv.c xine-lib-1.2-04.19.08/src/video_out/video_out_xv.c --- xine-lib-1.2-04-19-08.org/src/video_out/video_out_xv.c 2008-04-19 18:58:35.367992000 -0400 +++ xine-lib-1.2-04.19.08/src/video_out/video_out_xv.c 2008-05-31 14:50:43.290587000 -0400 @@ -58,6 +58,7 @@ #define LOG_MODULE "video_out_xv" #define LOG_VERBOSE +//#define LOG /* #define LOG */ @@ -70,6 +71,9 @@ #include #include "x11osd.h" #include "xv_common.h" +#include + +int display_half_frames = 0; #define LOCK_DISPLAY(this) {if(this->lock_display) this->lock_display(this->user_data); \ else XLockDisplay(this->display);} @@ -126,7 +130,11 @@ struct xv_driver_s { int use_pitch_alignment; xv_property_t props[VO_NUM_PROPERTIES]; uint32_t capabilities; + int h264_stream; + int osd_active; + int disable_deinterlace_for_osd; + int deinterlace_enabled; int ovl_changed; xv_frame_t *recent_frames[VO_NUM_RECENT_FRAMES]; xv_frame_t *cur_frame; @@ -166,6 +174,31 @@ static int gX11Fail; static const char *const prefer_types[] = VIDEO_DEVICE_XV_PREFER_TYPES; +static void compute_windowed_size(xv_driver_t *this); +static int draw_scaled_osd(xv_driver_t *this, xv_frame_t *video_frame); + +static void reset_frame_YUY2(vo_frame_t *dst, int w, int h); +static void reset_frame_YV12(vo_frame_t *dst, int w, int h); +static void vdr_video_scale_YUY2(xv_driver_t *driver, vo_frame_t *src, vo_frame_t *dst, int w, int h); +static void vdr_video_scale_YV12(xv_driver_t *driver, vo_frame_t *src, vo_frame_t *dst, int w, int h); + +static int screen_out_scaled; +static xv_frame_t *osd_frame; +static int draw_osd_frame; + +static int windowed_w_ref; +static int windowed_h_ref; + +static int windowed_x; +static int windowed_y; +static int windowed_width; +static int windowed_height; + +static int screen_out_x; +static int screen_out_y; +static int screen_out_width; +static int screen_out_height; + static uint32_t xv_get_capabilities (vo_driver_t *this_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -253,6 +286,11 @@ static XvImage *create_ximage (xv_driver unsigned int xv_format; XvImage *image = NULL; + if (width <= 0) + width = 1; + if (height <= 0) + height = 1; + if (this->use_pitch_alignment) { lprintf ("use_pitch_alignment old width=%d",width); width = (width + 7) & ~0x7; @@ -527,7 +565,27 @@ static void xv_compute_ideal_size (xv_dr static void xv_compute_output_size (xv_driver_t *this) { +//printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); +//printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); +//printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); + +//printf("xxxx OUTPUT %d %d %d %d\n", this->sc.output_xoffset, this->sc.output_yoffset, +// this->sc.output_width, this->sc.output_height); +//printf("xxxx DISPLAYED %d %d %d %d\n", this->sc.displayed_xoffset, this->sc.displayed_yoffset, +// this->sc.displayed_width, this->sc.displayed_height); + _x_vo_scale_compute_output_size( &this->sc ); + +//printf("yyyy OUTPUT %d %d %d %d\n", this->sc.output_xoffset, this->sc.output_yoffset, +// this->sc.output_width, this->sc.output_height); +//printf("yyyy DISPLAYED %d %d %d %d\n", this->sc.displayed_xoffset, this->sc.displayed_yoffset, +// this->sc.displayed_width, this->sc.displayed_height); + +//printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); +//printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); +//printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); + + compute_windowed_size(this); } static void xv_overlay_begin (vo_driver_t *this_gen, @@ -555,6 +613,8 @@ static void xv_overlay_end (vo_driver_t UNLOCK_DISPLAY(this); } + if (this->ovl_changed) draw_osd_frame = 1; + this->ovl_changed = 0; } @@ -564,6 +624,7 @@ static void xv_overlay_blend (vo_driver_ xv_frame_t *frame = (xv_frame_t *) frame_gen; if (overlay->rle) { + this->osd_active = 1; if( overlay->unscaled ) { if( this->ovl_changed && this->xoverlay ) { LOCK_DISPLAY(this); @@ -571,6 +632,10 @@ static void xv_overlay_blend (vo_driver_ UNLOCK_DISPLAY(this); } } else { + if (screen_out_scaled) { + frame = osd_frame; +// memset(frame->image->data,0,frame->width*frame->height); + } if (frame->format == XINE_IMGFMT_YV12) _x_blend_yuv(frame->vo_frame.base, overlay, frame->width, frame->height, frame->vo_frame.pitches, @@ -656,10 +721,19 @@ static double timeOfDay() static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; xv_frame_t *frame = (xv_frame_t *) frame_gen; + int disable_deinterlace = 0; /* printf (LOG_MODULE ": xv_display_frame...\n"); */ + /* Check deinterlace disable for OSD */ + disable_deinterlace = this->osd_active & this->disable_deinterlace_for_osd; + if (disable_deinterlace) { + xine_set_param(frame->vo_frame.stream, XINE_PARAM_VO_DEINTERLACE, 0); + } else { + xine_set_param(frame->vo_frame.stream, XINE_PARAM_VO_DEINTERLACE, 1); + } + /* * queue frames (deinterlacing) * free old frames @@ -667,6 +741,15 @@ static void xv_display_frame (vo_driver_ xv_add_recent_frame (this, frame); /* deinterlacing */ + if (this->osd_active && frame->vo_frame.progressive_frame && frame->vo_frame.duration < 2000 && frame->width > 1200) { + display_half_frames = display_half_frames ? 0 : 1; + if (!display_half_frames) + return; + } + + /* Reset osd_active flag*/ + this->osd_active = 0; + this->cur_frame = frame; /* @@ -686,43 +769,59 @@ static void xv_display_frame (vo_driver_ */ xv_redraw_needed (this_gen); { - double start_time; - double end_time; - double elapse_time; - int factor; +// double start_time; +// double end_time; +// double elapse_time; +// int factor; LOCK_DISPLAY(this); - start_time = timeOfDay(); +// start_time = timeOfDay(); + int osd_displayed = 0; + if (screen_out_scaled) { + osd_displayed = draw_scaled_osd(this, frame); + } + +// compute_windowed_size(this); +// fprintf(stdout,"\nScreen out x=%d, Screen out y=%d\n",screen_out_x, screen_out_y); +// fprintf(stdout,"Screen out width=%d, Screen out height=%d\n\n",screen_out_width, screen_out_height); + + if (!osd_displayed) { if (this->use_shm) { XvShmPutImage(this->display, this->xv_port, this->drawable, this->gc, this->cur_frame->image, this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width, this->sc.displayed_height, - this->sc.output_xoffset, this->sc.output_yoffset, - this->sc.output_width, this->sc.output_height, True); + screen_out_x, screen_out_y, + screen_out_width, screen_out_height, True); +// this->sc.output_xoffset, this->sc.output_yoffset, +// this->sc.output_width, this->sc.output_height, True); } else { XvPutImage(this->display, this->xv_port, this->drawable, this->gc, this->cur_frame->image, this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width, this->sc.displayed_height, - this->sc.output_xoffset, this->sc.output_yoffset, - this->sc.output_width, this->sc.output_height); + screen_out_x, screen_out_y, + screen_out_width, screen_out_height); +// this->sc.output_xoffset, this->sc.output_yoffset, +// this->sc.output_width, this->sc.output_height); + } } XSync(this->display, False); - end_time = timeOfDay(); +// end_time = timeOfDay(); UNLOCK_DISPLAY(this); - +/* elapse_time = end_time - start_time; factor = (int)(elapse_time/(1.0/60.0)); if( factor > 1 ) { - lprintf( "%s PutImage %dX interval (%fs)\n", - log_line_prefix(), factor, elapse_time ); + lprintf( "PutImage %dX interval (%fs)\n", + factor, elapse_time ); } +*/ } /* @@ -730,6 +829,34 @@ static void xv_display_frame (vo_driver_ */ } +static int draw_scaled_osd(xv_driver_t *this, xv_frame_t *video_frame) { + if (!draw_osd_frame) return 0; + draw_osd_frame = 0; + if (this->xv_format_yv12 != 0) { + vdr_video_scale_YV12(this, video_frame, osd_frame, osd_frame->width, osd_frame->height); + } + else { + vdr_video_scale_YUY2(this, video_frame, osd_frame, osd_frame->width, osd_frame->height); + } + + if (this->use_shm) { + XvShmPutImage(this->display, this->xv_port, + this->drawable, this->gc, osd_frame->image, + this->sc.displayed_xoffset, this->sc.displayed_yoffset, + this->sc.displayed_width, this->sc.displayed_height, + this->sc.output_xoffset, this->sc.output_yoffset, + this->sc.output_width, this->sc.output_height, False); + } else { + XvPutImage(this->display, this->xv_port, + this->drawable, this->gc, osd_frame->image, + this->sc.displayed_xoffset, this->sc.displayed_yoffset, + this->sc.displayed_width, this->sc.displayed_height, + this->sc.output_xoffset, this->sc.output_yoffset, + this->sc.output_width, this->sc.output_height); + } + return 1; +} + static int xv_get_property (vo_driver_t *this_gen, int property) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -854,7 +981,7 @@ static void xv_get_property_min_max (vo_ static int xv_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) { xv_driver_t *this = (xv_driver_t *) this_gen; - +fprintf(stdout,"Data type = %d\n",data_type); switch (data_type) { #ifndef XINE_DISABLE_DEPRECATED_FEATURES case XINE_GUI_SEND_COMPLETION_EVENT: @@ -874,15 +1001,15 @@ static int xv_gui_data_exchange (vo_driv this->drawable, this->gc, this->cur_frame->image, this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width, this->sc.displayed_height, - this->sc.output_xoffset, this->sc.output_yoffset, - this->sc.output_width, this->sc.output_height, True); + screen_out_x, screen_out_y, + screen_out_width, screen_out_height, True); } else { XvPutImage(this->display, this->xv_port, this->drawable, this->gc, this->cur_frame->image, this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width, this->sc.displayed_height, - this->sc.output_xoffset, this->sc.output_yoffset, - this->sc.output_width, this->sc.output_height); + screen_out_x, screen_out_y, + screen_out_width, screen_out_height); } XSetForeground (this->display, this->gc, this->black.pixel); @@ -932,6 +1059,47 @@ static int xv_gui_data_exchange (vo_driv } break; + case XINE_EVENT_VDR_SETVIDEOWINDOW: + { + fprintf(stdout,"XINE_EVENT_VDR_SETVIDEOWINDOW\n"); + vdr_set_video_window_data_t *event_data = (vdr_set_video_window_data_t *)data; + if (event_data->w == event_data->w_ref && event_data->h == event_data->h_ref) { + screen_out_scaled = 0; + compute_windowed_size(this); + } + else { + XLockDisplay (this->display); + + windowed_w_ref = event_data->w_ref; + windowed_h_ref = event_data->h_ref; + + windowed_x = event_data->x; + windowed_y = event_data->y; + windowed_width = event_data->w; + windowed_height = event_data->h; + + screen_out_scaled = 1; + compute_windowed_size(this); + if (!osd_frame) { + osd_frame = (xv_frame_t *)xv_alloc_frame(this); + } + int format = (this->xv_format_yv12 != 0) ? XINE_IMGFMT_YV12 : XINE_IMGFMT_YUY2; + xv_update_frame_format( + this, osd_frame, + this->sc.displayed_width, this->sc.displayed_height, + (double)this->sc.displayed_width/(double)this->sc.displayed_height, + format, VO_BOTH_FIELDS); + if (format == XINE_IMGFMT_YV12) { + reset_frame_YV12(osd_frame, osd_frame->width, osd_frame->height); + } + else { + reset_frame_YUY2(osd_frame, osd_frame->width, osd_frame->height); + } + XUnlockDisplay (this->display); + } + break; + } + default: return -1; } @@ -939,6 +1107,21 @@ static int xv_gui_data_exchange (vo_driv return 0; } +static void compute_windowed_size(xv_driver_t *this) { + if (screen_out_scaled) { + screen_out_x = screen_out_x + (this->sc.output_width*windowed_x)/windowed_w_ref; + screen_out_y = (this->sc.output_height*windowed_y)/windowed_h_ref; + screen_out_width = ((this->sc.output_width)*windowed_width)/windowed_w_ref + 2; + screen_out_height = (this->sc.output_height*windowed_height)/windowed_h_ref + 2; + } + else { + screen_out_x = this->sc.output_xoffset; + screen_out_y = this->sc.output_yoffset; + screen_out_width = this->sc.output_width; + screen_out_height = this->sc.output_height; + } +} + static void xv_store_port_attribute(xv_driver_t *this, char *name) { Atom atom; xv_portattribute_t *attr; @@ -1154,6 +1337,12 @@ static void xv_update_xv_pitch_alignment this->use_pitch_alignment = entry->num_value; } +static void xv_update_disable_deinterlace_for_osd(void *this_gen, xine_cfg_entry_t *entry) { + xv_driver_t *this = (xv_driver_t *) this_gen; + + this->disable_deinterlace_for_osd = entry->num_value; +} + static int xv_open_port (xv_driver_t *this, XvPortID port) { int ret; x11_InstallXErrorHandler (this); @@ -1493,6 +1682,15 @@ static vo_driver_t *open_plugin_2 (video VIDEO_DEVICE_XV_PITCH_ALIGNMENT_HELP, 10, xv_update_xv_pitch_alignment, this); + this->disable_deinterlace_for_osd = + config->register_bool (config, "video.device.disable_deinterlace_for_osd", 1, + _("Don't use deinterlacing while a OSD is active."), + _("Deinterlacing requires significant CPU time. Disabling\n" + "on demand should result in a better OSD picture.\n"), + 10, xv_update_disable_deinterlace_for_osd, this); + + this->deinterlace_enabled = 0; + LOCK_DISPLAY(this); if(this->use_colorkey==1) { this->xoverlay = x11osd_create (this->xine, this->display, this->screen, @@ -1573,3 +1771,195 @@ const plugin_info_t xine_plugin_info[] E { PLUGIN_VIDEO_OUT, 22, "xv", XINE_VERSION_CODE, &vo_info_xv_2, init_class_2 }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; + +/* + * Copied from vdr_post plugin. + * Extracted reset function out of vdr_video_scale into a separate routine + */ + +static inline void reset_frame(register uint8_t *dst, register int y_inc, register int x_inc, int w_dst, int h_dst, register int init) +{ + register int yy, xx; + + for (yy = 0; yy < h_dst; yy++) + { + uint8_t *dst0 = dst; + + for (xx = 0; xx < w_dst; xx++) + { + *dst0 = init; + dst0 += x_inc; + } + + dst += y_inc; + } + +} + +static void reset_frame_YUY2(vo_frame_t *dst, int w, int h) +{ + int offset; + + if (w < 0) + w = 0; + + if (h < 0) + h = 0; + + offset = dst->pitches[ 0 ] * dst->crop_top + 2 * dst->crop_left; + reset_frame(&dst->base[ 0 ][ 0 ] + offset, dst->pitches[ 0 ], 2, w, h, 0x00); + offset = dst->pitches[ 0 ] * dst->crop_top + 4 * ((dst->crop_left + 1) / 2); + reset_frame(&dst->base[ 0 ][ 1 ] + offset, dst->pitches[ 0 ], 4, (w + 1) / 2, h, 0x80); + offset = dst->pitches[ 0 ] * dst->crop_top + 4 * ((dst->crop_left + 1) / 2); + reset_frame(&dst->base[ 0 ][ 3 ] + offset, dst->pitches[ 0 ], 4, (w + 1) / 2, h, 0x80); +} + +static void reset_frame_YV12(vo_frame_t *dst, int w, int h) +{ + int offset; + + if (w < 0) + w = 0; + + if (h < 0) + h = 0; + + offset = dst->pitches[ 0 ] * dst->crop_top + 1 * dst->crop_left; + reset_frame(&dst->base[ 0 ][ 0 ] + offset, dst->pitches[ 0 ], 1, w, h, 0x00); + offset = dst->pitches[ 1 ] * ((dst->crop_top + 1) / 2) + 1 * ((dst->crop_left + 1) / 2); + reset_frame(&dst->base[ 1 ][ 0 ] + offset, dst->pitches[ 1 ], 1, (w + 1) / 2, (h + 1) / 2, 0x80); + offset = dst->pitches[ 2 ] * ((dst->crop_top + 1) / 2) + 1 * ((dst->crop_left + 1) / 2); + reset_frame(&dst->base[ 2 ][ 0 ] + offset, dst->pitches[ 2 ], 1, (w + 1) / 2, (h + 1) / 2, 0x80); +} + +static inline void vdr_video_scale(register uint8_t *src, register uint8_t *dst, register int y_inc, register int x_inc, int w_dst, int h_dst, int x, int y, int w, int h, int w_ref, int h_ref, register int init) +{ + int x0 = x * w_dst / w_ref; + int y0 = y * h_dst / h_ref; + + int x1 = ((x + w) * w_dst - 1 + w_ref) / w_ref; + int y1 = ((y + h) * h_dst - 1 + h_ref) / h_ref; + + int dx = x1 - x0; + int dy = y1 - y0; + + register int yy, xx; + + int dy2 = dy + dy; + int h_dst2 = h_dst + h_dst; + int y_eps = h_dst - dy2; + + int dx2 = dx + dx; + int w_dst2 = w_dst + w_dst; + int x_eps0 = w_dst - dx2; + + for (yy = 0; yy < y0; yy++) + { + uint8_t *dst0 = dst; + + for (xx = 0; xx < w_dst; xx++) + { +// *dst0 = init; + dst0 += x_inc; + } + + dst += y_inc; + } + + for (yy = y0; yy < y1; yy++) + { + uint8_t *dst0 = dst; + uint8_t *src0 = src; + + int x_eps = x_eps0; + + for (xx = 0; xx < x0; xx++) + { +// *dst0 = init; + dst0 += x_inc; + } + + for (xx = x0; xx < x1; xx++) + { +// *dst0 = *src0; + dst0 += x_inc; + + x_eps += w_dst2; + while (x_eps >= 0) + { + src0 += x_inc; + x_eps -= dx2; + } + } + + for (xx = x1; xx < w_dst; xx++) + { +// *dst0 = init; + dst0 += x_inc; + } + + dst += y_inc; + + y_eps += h_dst2; + while (y_eps >= 0) + { + src += y_inc; + y_eps -= dy2; + } + } + + for (yy = y1; yy < h_dst; yy++) + { + uint8_t *dst0 = dst; + + for (xx = 0; xx < w_dst; xx++) + { +// *dst0 = init; + dst0 += x_inc; + } + + dst += y_inc; + } +} + +static void vdr_video_scale_YUY2(xv_driver_t *this, vo_frame_t *src, vo_frame_t *dst, int w, int h) +{ + int offset; + + if (w < 0) + w = 0; + + if (h < 0) + h = 0; + + offset = dst->pitches[ 0 ] * dst->crop_top + 2 * dst->crop_left; + vdr_video_scale(&src->base[ 0 ][ 0 ] + offset, &dst->base[ 0 ][ 0 ] + offset, dst->pitches[ 0 ], 2, w , h, + 0,0, screen_out_width, screen_out_height, this->sc.output_width, this->sc.output_height, 0x00); + offset = dst->pitches[ 0 ] * dst->crop_top + 4 * ((dst->crop_left + 1) / 2); + vdr_video_scale(&src->base[ 0 ][ 1 ] + offset, &dst->base[ 0 ][ 1 ] + offset, dst->pitches[ 0 ], 4, (w + 1) / 2, h, + 0,0, screen_out_width, screen_out_height, this->sc.output_width, this->sc.output_height, 0x80); + offset = dst->pitches[ 0 ] * dst->crop_top + 4 * ((dst->crop_left + 1) / 2); + vdr_video_scale(&src->base[ 0 ][ 3 ] + offset, &dst->base[ 0 ][ 3 ] + offset, dst->pitches[ 0 ], 4, (w + 1) / 2, h, + 0,0, screen_out_width, screen_out_height, this->sc.output_width, this->sc.output_height, 0x80); +} + +static void vdr_video_scale_YV12(xv_driver_t *this, vo_frame_t *src, vo_frame_t *dst, int w, int h) +{ + int offset; + + if (w < 0) + w = 0; + + if (h < 0) + h = 0; + + offset = dst->pitches[ 0 ] * dst->crop_top + 1 * dst->crop_left; + vdr_video_scale(&src->base[ 0 ][ 0 ] + offset, &dst->base[ 0 ][ 0 ] + offset, dst->pitches[ 0 ], 1, w , h , + 0,0, screen_out_width, screen_out_height, this->sc.output_width, this->sc.output_height, 0x00); + offset = dst->pitches[ 1 ] * ((dst->crop_top + 1) / 2) + 1 * ((dst->crop_left + 1) / 2); + vdr_video_scale(&src->base[ 1 ][ 0 ] + offset, &dst->base[ 1 ][ 0 ] + offset, dst->pitches[ 1 ], 1, (w + 1) / 2, (h + 1) / 2, + 0,0, screen_out_width, screen_out_height, this->sc.output_width, this->sc.output_height, 0x80); + offset = dst->pitches[ 2 ] * ((dst->crop_top + 1) / 2) + 1 * ((dst->crop_left + 1) / 2); + vdr_video_scale(&src->base[ 2 ][ 0 ] + offset, &dst->base[ 2 ][ 0 ] + offset, dst->pitches[ 2 ], 1, (w + 1) / 2, (h + 1) / 2, + 0,0, screen_out_width, screen_out_height, this->sc.output_width, this->sc.output_height, 0x80); +} diff -Naurpb xine-lib-1.2-04-19-08.org/src/video_out/video_out_xxmc.c xine-lib-1.2-04.19.08/src/video_out/video_out_xxmc.c --- xine-lib-1.2-04-19-08.org/src/video_out/video_out_xxmc.c 2008-04-19 18:58:35.379993000 -0400 +++ xine-lib-1.2-04.19.08/src/video_out/video_out_xxmc.c 2008-05-21 12:23:00.523062000 -0400 @@ -38,6 +38,21 @@ #include #include "xv_common.h" +static void xvmc_sync_surface(xxmc_driver_t *this, XvMCSurface * srf); +static int xxmc_xvmc_surface_displaying(xxmc_driver_t *this, XvMCSurface *surface); + +inline static int xx44_paletteIndex(xx44_palette_t *p, int color, uint32_t clut); +inline static void memblend_xx44(uint8_t *mem,uint8_t val, register size_t size, uint8_t mask); +static void _x_blend_xx44_rle (uint8_t *dst_img, vo_overlay_t *img_overl, + int dst_width, int dst_height, int dst_pitch, + alphablend_t *extra_data, + xx44_palette_t *palette,int ia44); + +//int osd_active = 0; + +static int SUBPIC_WIDTH=720; +static int SUBPIC_HEIGHT=480; + static int gX11Fail; static void xxmc_frame_updates(xxmc_driver_t *driver, xxmc_frame_t *frame, @@ -209,24 +224,33 @@ static void xxmc_xvmc_destroy_subpicture pthread_mutex_unlock(&handler->mutex); } + +static int xxmc_xvmc_surface_displaying(xxmc_driver_t *this, XvMCSurface *surface) { + int status; + XvMCGetSurfaceStatus(this->display,surface,&status); + return status & XVMC_DISPLAYING; +} + static XvMCSurface *xxmc_xvmc_alloc_surface(xxmc_driver_t *this, XvMCContext *context) { xvmc_surface_handler_t *handler = &this->xvmc_surf_handler; - int i; +// int status; + int i,t; pthread_mutex_lock(&handler->mutex); - xxmc_xvmc_dump_surfaces(this); +// xxmc_xvmc_dump_surfaces(this); for (i=0; isurfValid[i] && !handler->surfInUse[i]) { + if (handler->surfValid[i] && !handler->surfInUse[i] && + !xxmc_xvmc_surface_displaying(this, handler->surfaces + i)) { handler->surfInUse[i] = 1; - xxmc_xvmc_dump_surfaces(this); +// xxmc_xvmc_dump_surfaces(this); pthread_mutex_unlock(&handler->mutex); return handler->surfaces + i; } } for (i=0; isurfInUse[i]) { + if (!handler->surfValid[i] && !handler->surfInUse[i]) { XVMCLOCKDISPLAY( this->display ); if (Success != XvMCCreateSurface( this->display, context, handler->surfaces + i)) { @@ -243,6 +267,20 @@ static XvMCSurface *xxmc_xvmc_alloc_surf return handler->surfaces + i; } } + + // all surfaces are busy, wait for a surface to become free + for(t=0;t<1000;t++){ + xine_usec_sleep(1000);//1ms + for (i=0; isurfValid[i] && !handler->surfInUse[i] && + !xxmc_xvmc_surface_displaying(this, handler->surfaces + i)) { + handler->surfInUse[i] = 1; + pthread_mutex_unlock(&handler->mutex); + return handler->surfaces + i; + } + } + } + pthread_mutex_unlock(&handler->mutex); return NULL; } @@ -255,10 +293,10 @@ static void xxmc_xvmc_free_surface(xxmc_ if (index >= XVMC_MAX_SURFACES) return; pthread_mutex_lock(&handler->mutex); - xprintf (this->xine, XINE_VERBOSITY_DEBUG, - LOG_MODULE ": Disposing of surface %d\n",index); +// xprintf (this->xine, XINE_VERBOSITY_DEBUG, +// LOG_MODULE ": Disposing of surface %d\n",index); handler->surfInUse[index]--; - xxmc_xvmc_dump_surfaces(this); +// xxmc_xvmc_dump_surfaces(this); pthread_mutex_unlock(&handler->mutex); } @@ -285,8 +323,11 @@ static XvMCSubpicture *xxmc_xvmc_alloc_s xvmc_surface_handler_t *handler = &this->xvmc_surf_handler; int status; + width=SUBPIC_WIDTH; + height=SUBPIC_HEIGHT; + pthread_mutex_lock(&handler->mutex); - xxmc_xvmc_dump_subpictures(this); +// xxmc_xvmc_dump_subpictures(this); for (i=0; isubValid[i] && !handler->subInUse[i]) { XVMCLOCKDISPLAY( this->display ); @@ -299,7 +340,7 @@ static XvMCSubpicture *xxmc_xvmc_alloc_s if (status & XVMC_DISPLAYING) continue; handler->subInUse[i] = 1; - xxmc_xvmc_dump_subpictures(this); +// xxmc_xvmc_dump_subpictures(this); pthread_mutex_unlock(&handler->mutex); return handler->subpictures + i; } @@ -316,7 +357,7 @@ static XvMCSubpicture *xxmc_xvmc_alloc_s } XVMCUNLOCKDISPLAY( this->display ); xprintf (this->xine, XINE_VERBOSITY_DEBUG, - LOG_MODULE ": Created subpicture %d\n",i); + LOG_MODULE ": Created subpicture %d width=%d height=%d\n",i,(handler->subpictures + i)->width, (handler->subpictures + i)->height); handler->subInUse[i] = 1; handler->subValid[i] = 1; pthread_mutex_unlock(&handler->mutex); @@ -339,7 +380,7 @@ static void xxmc_xvmc_free_subpicture(xx xprintf (this->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": Disposing of subpicture %d\n",index); handler->subInUse[index] = 0; - xxmc_xvmc_dump_subpictures(this); +// xxmc_xvmc_dump_subpictures(this); pthread_mutex_unlock(&handler->mutex); } @@ -407,6 +448,8 @@ static void xvmc_flush(vo_frame_t *this_ *frame = XXMC_FRAME(this_gen); xxmc_driver_t *driver = (xxmc_driver_t *) this_gen->driver; +// XvMCFlushSurface( driver->display, frame->xvmc_surf );*********missed +// return; // ****************************************************missed xvmc_context_reader_lock( &driver->xvmc_lock ); @@ -841,7 +884,7 @@ static int xxmc_create_context(xxmc_driv curCap = driver->xvmc_cap + driver->xvmc_cur_cap; xprintf(driver->xine, XINE_VERBOSITY_LOG, - LOG_MODULE ": Creating new XvMC Context %d\n",curCap->type_id); + LOG_MODULE ": Creating new XvMC Context %d, width=%d, height=%d\n",curCap->type_id,width, height); XVMCLOCKDISPLAY( driver->display ); if (Success == XvMCCreateContext( driver->display, driver->xv_port, curCap->type_id, width, @@ -861,6 +904,10 @@ static void xxmc_setup_subpictures(xxmc_ xvmc_capabilities_t *curCap; XvMCSubpicture *sp; +// printf("xxmc_setup_subpictures: 908: width=%d, height=%d\n",width, height); + width = SUBPIC_WIDTH; + height = SUBPIC_HEIGHT; + if (driver->contextActive) { /* @@ -1022,6 +1069,7 @@ static int xxmc_xvmc_update_context(xxmc driver->xvmc_mpeg = xxmc->mpeg; driver->xvmc_width = width; driver->xvmc_height = height; + driver->context_changed = 1; return driver->contextActive; } @@ -1039,7 +1087,8 @@ static void xxmc_frame_updates(xxmc_driv */ if (frame->xvmc_surf) { - if (! xxmc_xvmc_surface_valid( driver, frame->xvmc_surf )) { + if (! xxmc_xvmc_surface_valid( driver, frame->xvmc_surf ) || + xxmc_xvmc_surface_displaying(driver, frame->xvmc_surf)) { xxmc_xvmc_free_surface(driver , frame->xvmc_surf); frame->xvmc_surf = NULL; } @@ -1382,7 +1431,6 @@ static void xxmc_compute_ideal_size (xxm _x_vo_scale_compute_ideal_size( &this->sc ); } - /* * make ideal width/height "fit" into the gui */ @@ -1445,8 +1493,8 @@ static void xxmc_overlay_begin (vo_drive this->first_overlay = 1; XVMCLOCKDISPLAY( this->display ); XvMCClearSubpicture(this->display, this->new_subpic, 0,0, - this->xvmc_width, - this->xvmc_height, 0x00); + this->new_subpic->width, + this->new_subpic->height, 0x00); XVMCUNLOCKDISPLAY( this->display ); _x_clear_xx44_palette(&this->palette); } @@ -1462,12 +1510,15 @@ static void xxmc_overlay_end (vo_driver_ xxmc_driver_t *this = (xxmc_driver_t *) this_gen; xxmc_frame_t *frame = (xxmc_frame_t *) vo_img; + // a quick check to see if there really is something for us to do here + if (!this->ovl_changed && this->first_overlay) return; if( this->ovl_changed && this->xoverlay ) { XLockDisplay (this->display); x11osd_expose(this->xoverlay); XUnlockDisplay (this->display); } +// else if ((frame->format == XINE_IMGFMT_XXMC) && this->hwSubpictures) { LOCK_AND_SURFACE_VALID( this, frame->xvmc_surf ); if (this->ovl_changed) { @@ -1495,15 +1546,15 @@ static void xxmc_overlay_end (vo_driver_ XVMCLOCKDISPLAY( this->display ); if (this->xvmc_backend_subpic ) { XvMCBlendSubpicture( this->display, frame->xvmc_surf, - this->old_subpic,0,0,this->xvmc_width, - this->xvmc_height, 0, 0, - this->xvmc_width, this->xvmc_height ); + this->old_subpic, + 0,0,this->old_subpic->width, this->old_subpic->height, + 0,0, this->xvmc_width, this->xvmc_height ); } else { XvMCBlendSubpicture2( this->display, frame->xvmc_surf, frame->xvmc_surf, - this->old_subpic, 0,0,this->xvmc_width, - this->xvmc_height,0,0,this->xvmc_width, - this->xvmc_height); + this->old_subpic, + 0,0,this->old_subpic->width, this->old_subpic->height, + 0,0,this->xvmc_width, this->xvmc_height); } XVMCUNLOCKDISPLAY( this->display ); } @@ -1520,7 +1571,8 @@ static void xxmc_overlay_blend (vo_drive xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen; if (overlay->rle) { - this->scaled_osd_active = !overlay->unscaled; +// this->scaled_osd_active = !overlay->unscaled; + this->scaled_osd_active = 1; if( overlay->unscaled ) { if( this->ovl_changed && this->xoverlay ) { XLockDisplay (this->display); @@ -1537,7 +1589,14 @@ static void xxmc_overlay_blend (vo_drive this->subImage->height); this->first_overlay = 0; } - _x_blend_xx44(this->subImage->data, overlay, this->subImage->width, + + xprintf(this->xine, XINE_VERBOSITY_LOG, + "video_out_xxmc: subpicture width=%d height=%d\n", this->subImage->width, this->subImage->height); + + xprintf(this->xine, XINE_VERBOSITY_LOG, + "video_out_xxmc: overlay width=%d height=%d\n", overlay->width, overlay->height); + + _x_blend_xx44_rle(this->subImage->data, overlay, this->subImage->width, this->subImage->height, this->subImage->width, &this->alphablend_extra_data, &this->palette, (this->subImage->id == FOURCC_IA44)); @@ -1581,6 +1640,125 @@ static void xxmc_overlay_blend (vo_drive } } +inline static int xx44_paletteIndex(xx44_palette_t *p, int color, uint32_t clut) +{ + + register unsigned int i; + register uint32_t *cluts = p->cluts; + register int tmp; + + if ((tmp = p->lookup_cache[color]) >= 0) + if (cluts[tmp] == clut) return tmp; + + for (i=0; imax_used; ++i) { + if (*cluts++ == clut) return p->lookup_cache[color] = i; + } + + if (p->max_used == p->size -1) { +// lprintf("video_out: Warning! Out of xx44 palette colors!\n"); + return 1; + } + p->cluts[p->max_used] = clut; + return p->lookup_cache[color] = p->max_used++; +} + +inline static void memblend_xx44(uint8_t *mem,uint8_t val, register size_t size, uint8_t mask) +{ + register uint8_t + masked_val; + + if (0 == (masked_val = val & mask)) return; + + while(size--) { + if ((*mem & mask) <= masked_val ) *mem = val; + mem++; + } +} + +static void _x_blend_xx44_rle (uint8_t *dst_img, vo_overlay_t *img_overl, + int dst_width, int dst_height, int dst_pitch, + alphablend_t *extra_data, + xx44_palette_t *palette,int ia44) +{ + int src_width, src_height; + register rle_elem_t *rle; + rle_elem_t *rle_limit; + int x_off, y_off; + register int x, y; + uint8_t norm_pixel; + register uint8_t *dst_y; + register uint8_t *dst; + uint8_t alphamask = (ia44) ? 0x0F : 0xF0; + int hili_right, hili_left; + int clip_right, clip_left, clip_top; + + if (!img_overl) + return; + + src_width = img_overl->width; + src_height = img_overl->height; + rle = img_overl->rle; + rle_limit = rle + img_overl->num_rle; + x_off = img_overl->x + extra_data->offset_x; + y_off = img_overl->y + extra_data->offset_y; + + dst_y = dst_img + dst_pitch*y_off + x_off; + + /* checks to avoid drawing overlay outside the destination buffer */ + if( (x_off + src_width) <= dst_width ) + clip_right = src_width; + else + clip_right = dst_width - x_off; + + if( x_off >= 0 ) + clip_left = 0; + else + clip_left = -x_off; + + if( y_off >= 0 ) + clip_top = 0; + else + clip_top = -y_off; + + if( (src_height + y_off) > dst_height ) + src_height = dst_height - y_off; + + /* make highlight area fit into clip area */ + if( img_overl->hili_right <= clip_right ) + hili_right = img_overl->hili_right; + else + hili_right = clip_right; + + if( img_overl->hili_left >= clip_left ) + hili_left = img_overl->hili_left; + else + hili_left = clip_left; + + for (y = 0; y < src_height; y++) { + + dst = dst_y; + + for (x = 0; x < src_width;) { + int len = (x + rle->len > clip_right) ? clip_right - x : rle->len; +// int clipped = (y < clip_top); + + if (len > 0) { + norm_pixel = (uint8_t)((xx44_paletteIndex(palette,rle->color, + img_overl->color[rle->color]) << 4) | + (img_overl->trans[rle->color] & 0x0F)); + memblend_xx44(dst,norm_pixel,len, alphamask); + dst += len; + } + x += rle->len; + rle++; + if (rle >= rle_limit) break; + } + dst_y += dst_pitch; + } +} + + +inline static void xxmc_add_recent_frame (xxmc_driver_t *this, xxmc_frame_t *frame) { int i; @@ -1648,8 +1826,9 @@ static void xxmc_display_frame (vo_drive * other than 100 %, so let's disable deinterlacing at all for this frame */ if (this->deinterlace_enabled && this->bob) { - disable_deinterlace = this->disable_bob_for_progressive_frames && frame->vo_frame.progressive_frame - || this->disable_bob_for_scaled_osd && this->scaled_osd_active +// printf("disable bob for progressive=%d, progressive frame=%d,disable bob for osd=%d,osd active=%d\n",this->disable_bob_for_progressive_frames, frame->vo_frame.progressive_frame, this->disable_bob_for_scaled_osd, this->scaled_osd_active); + disable_deinterlace = (this->disable_bob_for_progressive_frames && frame->vo_frame.progressive_frame) + || (this->disable_deinterlace_for_osd && this->scaled_osd_active) || !frame->vo_frame.stream || xine_get_param(frame->vo_frame.stream, XINE_PARAM_FINE_SPEED) != XINE_FINE_SPEED_NORMAL; if (!disable_deinterlace) { @@ -1698,9 +1877,11 @@ static void xxmc_display_frame (vo_drive */ if ( (frame->width != this->sc.delivered_width) || (frame->height != this->sc.delivered_height) - || (frame->ratio != this->sc.delivered_ratio) ) { + || (frame->ratio != this->sc.delivered_ratio) + || this->context_changed ==1) { lprintf("frame format changed\n"); this->sc.force_redraw = 1; /* trigger re-calc of output size */ + this->context_changed = 0; } /* @@ -1715,16 +1896,16 @@ static void xxmc_display_frame (vo_drive xxmc_redraw_needed (this_gen); if (frame->format == XINE_IMGFMT_XXMC) { XVMCLOCKDISPLAY( this->display ); - XvMCSyncSurface( this->display, frame->xvmc_surf ); - XLockDisplay( this->display ); /* blocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */ +// XvMCSyncSurface( this->display, frame->xvmc_surf ); +// XLockDisplay( this->display ); /* blocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */ XvMCPutSurface( this->display, frame->xvmc_surf , this->drawable, this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width, this->sc.displayed_height, this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_width, this->sc.output_height, this->cur_field); - XUnlockDisplay( this->display ); /* unblocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */ - XVMCUNLOCKDISPLAY( this->display ); +// XUnlockDisplay( this->display ); /* unblocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */ +// XVMCUNLOCKDISPLAY( this->display ); if (this->deinterlace_enabled && !disable_deinterlace && this->bob) { struct timeval tv_middle; long us_spent_so_far, us_per_field = frame->vo_frame.duration * 50 / 9; @@ -1742,27 +1923,29 @@ static void xxmc_display_frame (vo_drive * field time so far */ if (4 * us_spent_so_far < 3 * us_per_field) { - long us_delay = (us_per_field - 2000) - us_spent_so_far; +/* long us_delay = (us_per_field - 2000) - us_spent_so_far; if (us_delay > 0) { xvmc_context_reader_unlock( &this->xvmc_lock ); xine_usec_sleep(us_delay); LOCK_AND_SURFACE_VALID( this, frame->xvmc_surf ); } - +*/ this->cur_field = (frame->vo_frame.top_field_first) ? XVMC_BOTTOM_FIELD : XVMC_TOP_FIELD; - XVMCLOCKDISPLAY( this->display ); - XLockDisplay( this->display ); /* blocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */ +// XVMCLOCKDISPLAY( this->display ); +// XLockDisplay( this->display ); /* blocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */ XvMCPutSurface( this->display, frame->xvmc_surf , this->drawable, this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width, this->sc.displayed_height, this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_width, this->sc.output_height, this->cur_field); - XUnlockDisplay( this->display ); /* unblocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */ - XVMCUNLOCKDISPLAY( this->display ); +// XUnlockDisplay( this->display ); /* unblocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */ +// XVMCUNLOCKDISPLAY( this->display ); } } + XFlush(this->display); + XVMCUNLOCKDISPLAY( this->display ); } else { XLockDisplay (this->display); if (this->use_shm) { @@ -1970,6 +2153,7 @@ static int xxmc_gui_data_exchange (vo_dr this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_width, this->sc.output_height, this->cur_field); + XFlush(this->display); XVMCUNLOCKDISPLAY( this->display ); } else { XLockDisplay (this->display); @@ -2232,10 +2416,10 @@ static void xxmc_update_disable_bob_for_ this->disable_bob_for_progressive_frames = entry->num_value; } -static void xxmc_update_disable_bob_for_scaled_osd(void *this_gen, xine_cfg_entry_t *entry) { +static void xxmc_update_disable_deinterlace_for_osd(void *this_gen, xine_cfg_entry_t *entry) { xxmc_driver_t *this = (xxmc_driver_t *) this_gen; - this->disable_bob_for_scaled_osd = entry->num_value; + this->disable_deinterlace_for_osd = entry->num_value; } static int xxmc_open_port (xxmc_driver_t *this, XvPortID port) { @@ -2729,31 +2913,31 @@ static vo_driver_t *open_plugin (video_d "Experimental.\n"), 10, xxmc_update_cpu_save, this); this->reverse_nvidia_palette = - config->register_bool (config, "video.device.xvmc_nvidia_color_fix", 0, + config->register_bool (config, "video.device.xvmc_nvidia_color_fix", 1, _("Fix buggy NVIDIA XvMC subpicture colours"), _("There's a bug in NVIDIA's XvMC lib that makes red OSD colours\n" "look blue and vice versa. This option provides a workaround.\n"), 10, xxmc_update_nvidia_fix, this); this->bob = - config->register_bool (config, "video.device.xvmc_bob_deinterlacing", 0, + config->register_bool (config, "video.device.xvmc_bob_deinterlacing", 1, _("Use bob as accelerated deinterlace method."), _("When interlacing is enabled for hardware accelerated frames,\n" "alternate between top and bottom field at double the frame rate.\n"), 10, xxmc_update_bob, this); this->disable_bob_for_progressive_frames = - config->register_bool (config, "video.device.xvmc_disable_bob_deinterlacing_for_progressive_frames", 0, + config->register_bool (config, "video.device.xvmc_disable_bob_deinterlacing_for_progressive_frames", 1, _("Don't use bob deinterlacing for progressive frames."), _("Progressive frames don't need deinterlacing, so disabling it on\n" "demand should result in a better picture.\n"), 10, xxmc_update_disable_bob_for_progressive_frames, this); - this->disable_bob_for_scaled_osd = - config->register_bool (config, "video.device.xvmc_disable_bob_deinterlacing_for_scaled_osd", 0, - _("Don't use bob deinterlacing while a scaled OSD is active."), - _("Bob deinterlacing adds some noise to horizontal lines, so disabling it\n" + this->disable_deinterlace_for_osd = + config->register_bool (config, "video.device.disable_deinterlace_for_osd", 1, + _("Don't use deinterlacing while a OSD is active."), + _("Deinterlacing requires significant CPU time. Disabling\n" "on demand should result in a better OSD picture.\n"), - 10, xxmc_update_disable_bob_for_scaled_osd, this); + 10, xxmc_update_disable_deinterlace_for_osd, this); this->deinterlace_enabled = 0; this->cur_field = XVMC_FRAME_PICTURE; diff -Naurpb xine-lib-1.2-04-19-08.org/src/video_out/xvmc_mocomp.c xine-lib-1.2-04.19.08/src/video_out/xvmc_mocomp.c --- xine-lib-1.2-04-19-08.org/src/video_out/xvmc_mocomp.c 2008-04-19 18:58:35.386994000 -0400 +++ xine-lib-1.2-04.19.08/src/video_out/xvmc_mocomp.c 2008-04-19 18:47:35.655602000 -0400 @@ -91,6 +91,7 @@ static void xvmc_render_macro_blocks(vo_ flags, macroblocks->slices, 0, ¯oblocks->macro_blocks, ¯oblocks->blocks); + XvMCFlushSurface(this->display, current_frame->xvmc_surf); XVMCUNLOCKDISPLAY( this->display); } diff -Naurpb xine-lib-1.2-04-19-08.org/src/video_out/xxmc.h xine-lib-1.2-04.19.08/src/video_out/xxmc.h --- xine-lib-1.2-04-19-08.org/src/video_out/xxmc.h 2008-04-19 18:58:35.401995000 -0400 +++ xine-lib-1.2-04.19.08/src/video_out/xxmc.h 2008-05-21 07:51:17.238632000 -0400 @@ -92,7 +92,8 @@ #define FOURCC_IA44 0x34344149 #define FOURCC_AI44 0x34344941 -#define XVMC_MAX_SURFACES 16 +#define XVMC_MAX_SURFACES 8 +//#define XVMC_MAX_SURFACES 16 #define XVMC_MAX_SUBPICTURES 4 typedef struct xxmc_driver_s xxmc_driver_t; @@ -203,7 +204,7 @@ struct xxmc_driver_s { int cur_field; int bob; int disable_bob_for_progressive_frames; - int disable_bob_for_scaled_osd; + int disable_deinterlace_for_osd; int scaled_osd_active; x11osd *xoverlay; int xv_xoverlay_type; @@ -234,6 +235,7 @@ struct xxmc_driver_s { int cpu_save_enabled; int reverse_nvidia_palette; int context_flags; + int context_changed; /* * These variables are protected by the context lock: diff -Naurpb xine-lib-1.2-04-19-08.org/src/xine-engine/alphablend.c xine-lib-1.2-04.19.08/src/xine-engine/alphablend.c --- xine-lib-1.2-04-19-08.org/src/xine-engine/alphablend.c 2008-04-19 18:58:35.435997000 -0400 +++ xine-lib-1.2-04.19.08/src/xine-engine/alphablend.c 2008-05-27 17:50:10.000000000 -0400 @@ -1221,8 +1221,8 @@ void _x_blend_yuv (uint8_t *dst_base[3], return; /* make linebuffer transparent */ - memset(&(*blend_yuv_data)[ 0 ][ 0 ][ 0 ], 0, exact_blend_width_m2); - memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2); + xine_fast_memset(&(*blend_yuv_data)[ 0 ][ 0 ][ 0 ], 0, exact_blend_width_m2); + xine_fast_memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2); } rlelen=rle_remainder=0; @@ -1385,17 +1385,17 @@ void _x_blend_yuv (uint8_t *dst_base[3], if (enable_exact_blending) { /* remember opacity of current line */ - memset(&(*blend_yuv_data)[ 0 ][ (y + y_odd) & 1 ][ x + x_odd ], o, rle_this_bite); + xine_fast_memset(&(*blend_yuv_data)[ 0 ][ (y + y_odd) & 1 ][ x + x_odd ], o, rle_this_bite); any_line_buffered |= ((y + y_odd) & 1) ? 2 : 1; } if (o && !clipped) { if(o >= 15) { - memset(dst_y + x, my_clut[clr].y, rle_this_bite); + xine_fast_memset(dst_y + x, my_clut[clr].y, rle_this_bite); if (!enable_exact_blending) { if ((y + y_odd) & 1) { - memset(dst_cr + ((x + x_odd) >> 1), my_clut[clr].cr, (rle_this_bite+1) >> 1); - memset(dst_cb + ((x + x_odd) >> 1), my_clut[clr].cb, (rle_this_bite+1) >> 1); + xine_fast_memset(dst_cr + ((x + x_odd) >> 1), my_clut[clr].cr, (rle_this_bite+1) >> 1); + xine_fast_memset(dst_cb + ((x + x_odd) >> 1), my_clut[clr].cb, (rle_this_bite+1) >> 1); } } } else { @@ -1411,8 +1411,8 @@ void _x_blend_yuv (uint8_t *dst_base[3], if (enable_exact_blending) { /* remember chroma of current line */ - memset(&(*blend_yuv_data)[ 1 ][ (y + y_odd) & 1 ][ x + x_odd ], my_clut[ clr ].cr, rle_this_bite); - memset(&(*blend_yuv_data)[ 2 ][ (y + y_odd) & 1 ][ x + x_odd ], my_clut[ clr ].cb, rle_this_bite); + xine_fast_memset(&(*blend_yuv_data)[ 1 ][ (y + y_odd) & 1 ][ x + x_odd ], my_clut[ clr ].cr, rle_this_bite); + xine_fast_memset(&(*blend_yuv_data)[ 2 ][ (y + y_odd) & 1 ][ x + x_odd ], my_clut[ clr ].cb, rle_this_bite); } } } @@ -1428,7 +1428,7 @@ void _x_blend_yuv (uint8_t *dst_base[3], if (any_line_buffered) { if (!(any_line_buffered & 2)) { /* make second line transparent */ - memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2); + xine_fast_memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2); } blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, blend_yuv_data); @@ -1449,7 +1449,7 @@ void _x_blend_yuv (uint8_t *dst_base[3], if (any_line_buffered) { if (!(any_line_buffered & 2)) { /* make second line transparent */ - memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2); + xine_fast_memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2); } blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, blend_yuv_data); @@ -1664,7 +1664,7 @@ void _x_blend_yuy2 (uint8_t * dst_img, v return; /* make linebuffer transparent */ - memset(&(*blend_yuy2_data)[ 0 ][ 0 ], 0, exact_blend_width_m2); + xine_fast_memset(&(*blend_yuy2_data)[ 0 ][ 0 ], 0, exact_blend_width_m2); } rlelen=rle_remainder=0; @@ -1802,7 +1802,7 @@ void _x_blend_yuy2 (uint8_t * dst_img, v if (enable_exact_blending) { /* remember opacity of current line */ - memset(&(*blend_yuy2_data)[ 0 ][ x + x_odd ], o, rle_this_bite); + xine_fast_memset(&(*blend_yuy2_data)[ 0 ][ x + x_odd ], o, rle_this_bite); any_line_buffered = 1; } @@ -1864,8 +1864,8 @@ void _x_blend_yuy2 (uint8_t * dst_img, v if (enable_exact_blending) { /* remember chroma of current line */ - memset(&(*blend_yuy2_data)[ 1 ][ x + x_odd ], my_clut[ clr ].cr, rle_this_bite); - memset(&(*blend_yuy2_data)[ 2 ][ x + x_odd ], my_clut[ clr ].cb, rle_this_bite); + xine_fast_memset(&(*blend_yuy2_data)[ 1 ][ x + x_odd ], my_clut[ clr ].cr, rle_this_bite); + xine_fast_memset(&(*blend_yuy2_data)[ 2 ][ x + x_odd ], my_clut[ clr ].cb, rle_this_bite); } } else { dst += rle_this_bite*2; @@ -2142,7 +2142,7 @@ void _x_alphablend_init(alphablend_t *ex extra_data->offset_y = 0; extra_data->disable_exact_blending = - config->register_bool(config, "video.output.disable_exact_alphablend", 0, + config->register_bool(config, "video.output.disable_exact_alphablend", 1, _("disable exact alpha blending of overlays"), _("If you experience a performance impact when an On Screen Display or other " "overlays like DVD subtitles are active, then you might want to enable this option.\n" diff -Naurpb xine-lib-1.2-04-19-08.org/src/xine-engine/audio_decoder.c xine-lib-1.2-04.19.08/src/xine-engine/audio_decoder.c --- xine-lib-1.2-04-19-08.org/src/xine-engine/audio_decoder.c 2008-04-19 18:58:35.441998000 -0400 +++ xine-lib-1.2-04.19.08/src/xine-engine/audio_decoder.c 2008-04-24 10:13:40.423389000 -0400 @@ -480,7 +480,7 @@ int _x_audio_decoder_init (xine_stream_t num_buffers = stream->xine->config->register_num (stream->xine->config, "engine.buffers.audio_num_buffers", - 230, + 750, _("number of audio buffers"), _("The number of audio buffers (each is 8k in size) " "xine uses in its internal queue. Higher values " diff -Naurpb xine-lib-1.2-04-19-08.org/src/xine-engine/audio_out.c xine-lib-1.2-04.19.08/src/xine-engine/audio_out.c --- xine-lib-1.2-04-19-08.org/src/xine-engine/audio_out.c 2008-04-19 18:58:35.456999000 -0400 +++ xine-lib-1.2-04.19.08/src/xine-engine/audio_out.c 2008-05-18 14:16:13.825449000 -0400 @@ -1047,6 +1047,9 @@ static void *ao_loop (void *this_gen) { (this->clock->speed != XINE_FINE_SPEED_NORMAL && !this->slow_fast_audio) ) ) { +/* xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_out: XXXXXXXXXXXXXXXXXXXXXXX clock=%d\n", this->clock->speed);*/ + if (this->clock->speed != XINE_SPEED_PAUSE) { cur_time = this->clock->get_current_time (this->clock); @@ -1060,10 +1063,10 @@ static void *ao_loop (void *this_gen) { continue; } - if ((in_buf->vpts - cur_time) > 2 * 90000) +/* if ((in_buf->vpts - cur_time) > 2 * 90000) xprintf (this->xine, XINE_VERBOSITY_DEBUG, - "audio_out: vpts/clock error, in_buf->vpts=%" PRId64 " cur_time=%" PRId64 "\n", - in_buf->vpts, cur_time); + "audio_out: vpts/clock error, in_buf->vpts=%" PRId64 " cur_time=%" PRId64 " clock=%d\n", + in_buf->vpts, cur_time, this->clock->speed);*/ } lprintf ("loop:pause: I feel sleepy (%d buffers).\n", this->out_fifo->num_buffers); @@ -1095,7 +1098,7 @@ static void *ao_loop (void *this_gen) { delay = this->driver->delay(this->driver); while (delay < 0 && this->audio_loop_running) { /* Get the audio card into RUNNING state. */ - ao_fill_gap (this, 10000); /* FIXME, this PTS of 1000 should == period size */ + ao_fill_gap (this, 1000); /* FIXME, this PTS of 1000 should == period size */ delay = this->driver->delay(this->driver); } pthread_mutex_unlock( &this->driver_lock ); @@ -2143,7 +2146,7 @@ xine_audio_port_t *_x_ao_new_port (xine_ this->passthrough_offset = config->register_num (config, "audio.synchronization.passthrough_offset", - 0, + 12, _("offset for digital passthrough"), _("If you use an external surround decoder and " "audio is ahead or behind video, you can enter " diff -Naurpb xine-lib-1.2-04-19-08.org/src/xine-engine/metronom.c xine-lib-1.2-04.19.08/src/xine-engine/metronom.c --- xine-lib-1.2-04-19-08.org/src/xine-engine/metronom.c 2008-04-19 18:58:35.547005000 -0400 +++ xine-lib-1.2-04.19.08/src/xine-engine/metronom.c 2008-04-23 12:03:40.880624000 -0400 @@ -49,8 +49,8 @@ #define WRAP_THRESHOLD 120000 #define MAX_NUM_WRAP_DIFF 10 #define MAX_SCR_PROVIDERS 10 -#define VIDEO_DRIFT_TOLERANCE 45000 -#define AUDIO_DRIFT_TOLERANCE 45000 +#define VIDEO_DRIFT_TOLERANCE 45000 //original value +#define AUDIO_DRIFT_TOLERANCE 45000 //original value /* metronom video modes */ #define VIDEO_PREDICTION_MODE 0 /* use pts + frame duration */ diff -Naurpb xine-lib-1.2-04-19-08.org/src/xine-engine/post.c xine-lib-1.2-04.19.08/src/xine-engine/post.c --- xine-lib-1.2-04-19-08.org/src/xine-engine/post.c 2008-04-19 18:58:35.563006000 -0400 +++ xine-lib-1.2-04.19.08/src/xine-engine/post.c 2008-05-28 11:07:42.481252000 -0400 @@ -219,6 +219,7 @@ post_video_port_t *_x_post_intercept_vid post_in_t **input, post_out_t **output) { post_video_port_t *port = (post_video_port_t *)xine_xmalloc(sizeof(post_video_port_t)); + printf("_x_post_intercept_video_port\n"); if (!port) return NULL; diff -Naurpb xine-lib-1.2-04-19-08.org/src/xine-engine/video_decoder.c xine-lib-1.2-04.19.08/src/xine-engine/video_decoder.c --- xine-lib-1.2-04-19-08.org/src/xine-engine/video_decoder.c 2008-04-19 18:58:35.573007000 -0400 +++ xine-lib-1.2-04.19.08/src/xine-engine/video_decoder.c 2008-04-24 10:13:55.590493000 -0400 @@ -411,7 +411,7 @@ static void *video_decoder_loop (void *s if (_x_stream_info_get(stream, XINE_STREAM_INFO_IGNORE_SPU)) break; - xine_profiler_start_count (prof_spu_decode); +// xine_profiler_start_count (prof_spu_decode); running_ticket->acquire(running_ticket, 0); @@ -459,7 +459,7 @@ static void *video_decoder_loop (void *s running_ticket->renew(running_ticket, 0); running_ticket->release(running_ticket, 0); - xine_profiler_stop_count (prof_spu_decode); +// xine_profiler_stop_count (prof_spu_decode); } else if (buf->type != buftype_unknown) { xine_log (stream->xine, XINE_LOG_MSG, @@ -498,7 +498,7 @@ int _x_video_decoder_init (xine_stream_t num_buffers = stream->xine->config->register_num (stream->xine->config, "engine.buffers.video_num_buffers", - 500, + 1500, _("number of video buffers"), _("The number of video buffers (each is 8k in size) " "xine uses in its internal queue. Higher values " diff -Naurpb xine-lib-1.2-04-19-08.org/src/xine-engine/video_out.c xine-lib-1.2-04.19.08/src/xine-engine/video_out.c --- xine-lib-1.2-04-19-08.org/src/xine-engine/video_out.c 2008-04-19 18:58:35.588008000 -0400 +++ xine-lib-1.2-04.19.08/src/xine-engine/video_out.c 2008-05-18 14:15:04.088246000 -0400 @@ -51,7 +51,7 @@ #define NUM_FRAME_BUFFERS 15 #define MAX_USEC_TO_SLEEP 20000 -#define DEFAULT_FRAME_DURATION 3000 /* 30 frames per second */ +#define DEFAULT_FRAME_DURATION 3003 /* 29.97 frames per second */ /* wait this delay if the first frame is still referenced */ #define FIRST_FRAME_POLL_DELAY 3000 @@ -1013,14 +1013,14 @@ static void overlay_and_display_frame (v if(!img->proc_called ) vo_frame_driver_proc(img); - if (img->stream) { +/* if (img->stream) { int64_t diff; pthread_mutex_lock( &img->stream->current_extra_info_lock ); diff = img->extra_info->vpts - img->stream->current_extra_info->vpts; if ((diff > 3000) || (diff<-300000)) _x_extra_info_merge( img->stream->current_extra_info, img->extra_info ); pthread_mutex_unlock( &img->stream->current_extra_info_lock ); - } + }*/ if (this->overlay_source) { this->overlay_source->multiple_overlay_blend (this->overlay_source, @@ -1267,14 +1267,19 @@ static void *video_out_loop (void *this_ lprintf ("%" PRId64 " usec to sleep at master vpts %" PRId64 "\n", usec_to_sleep, vpts); - if ( (next_frame_vpts - vpts) > 2*90000 ) +/* if ( (next_frame_vpts - vpts) > 2*90000 ) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "video_out: YYYYYYYYYYYYYYYYYYYYYYY clock=%d\n", this->clock->speed); xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out: vpts/clock error, next_vpts=%" PRId64 " cur_vpts=%" PRId64 "\n", next_frame_vpts,vpts); + "video_out: vpts/clock error, next_vpts=%" PRId64 " cur_vpts=%" PRId64 "clock=%d\n", next_frame_vpts,vpts, this->clock->speed); + }*/ if (usec_to_sleep > 0) { if (0 == interruptable_sleep(this, usec_to_sleep)) break; + else + interruptable_sleep(this, 100); } if (this->discard_frames) diff -Naurpb xine-lib-1.2-04-19-08.org/src/xine-engine/video_overlay.c xine-lib-1.2-04.19.08/src/xine-engine/video_overlay.c --- xine-lib-1.2-04-19-08.org/src/xine-engine/video_overlay.c 2008-04-19 18:58:35.591008000 -0400 +++ xine-lib-1.2-04.19.08/src/xine-engine/video_overlay.c 2008-04-19 18:47:35.671603000 -0400 @@ -515,7 +515,7 @@ static void video_overlay_multiple_overl */ pthread_mutex_lock( &this->showing_mutex ); - if( output->overlay_begin ) + if( this->showing_changed && output->overlay_begin ) output->overlay_begin(output, vo_img, this->showing_changed); for( i = 0; enabled && output->overlay_blend && i < MAX_SHOWING; i++ ) { diff -Naurpb xine-lib-1.2-04-19-08.org/src/xine-utils/memcpy.c xine-lib-1.2-04.19.08/src/xine-utils/memcpy.c --- xine-lib-1.2-04-19-08.org/src/xine-utils/memcpy.c 2008-04-19 18:58:35.630011000 -0400 +++ xine-lib-1.2-04.19.08/src/xine-utils/memcpy.c 2008-05-27 17:50:06.000000000 -0400 @@ -535,3 +535,119 @@ void xine_probe_fast_memcpy(xine_t *xine free(buf2); } + +//////////////////////////////////////////////////////////////////////////////// +// memset +//////////////////////////////////////////////////////////////////////////////// +#define HAVE_ASM_SSE + +/* for small memory blocks (<256 bytes) this version is faster */ +#define small_memset(to,val,n)\ +{\ +register unsigned long int dummy;\ +__asm__ __volatile__(\ + "rep; stosb"\ + :"=&D"(to), "=&c"(dummy)\ + :"0" (to), "1" (n), "a"((char)val)\ + :"memory");\ +} + +#undef _MMREG_SIZE +#ifdef HAVE_ASM_SSE +#define _MMREG_SIZE 16 +#else +#define _MMREG_SIZE 64 +#endif + +#undef _MIN_LEN +#ifdef HAVE_MMX1 +#define _MIN_LEN 0x800 /* 2K blocks */ +#else +#define _MIN_LEN 0x40 /* 64-byte blocks */ +#endif + +/* Fast memory set. See comments for fast_memcpy */ +void * xine_fast_memset(void * to, int val, size_t len) +{ + void *retval; + size_t i; + unsigned char mm_reg[_MMREG_SIZE], *pmm_reg; + unsigned char *t = to; + retval = to; + if(len >= _MIN_LEN) + { + register unsigned long int delta; + delta = ((unsigned long int)to)&(_MMREG_SIZE-1); + if(delta) + { + delta=_MMREG_SIZE-delta; + len -= delta; + small_memset(t, val, delta); + } + i = len >> 7; /* len/128 */ + len&=127; + pmm_reg = mm_reg; + small_memset(pmm_reg,val,sizeof(mm_reg)); +#ifdef HAVE_ASM_SSE /* Only P3 (may be Cyrix3) */ + __asm__ __volatile__( + "movups (%0), %%xmm0\n" + :: "r"(mm_reg):"memory"); + for(; i>0; i--) + { + __asm__ __volatile__ ( + "movntps %%xmm0, (%0)\n" + "movntps %%xmm0, 16(%0)\n" + "movntps %%xmm0, 32(%0)\n" + "movntps %%xmm0, 48(%0)\n" + "movntps %%xmm0, 64(%0)\n" + "movntps %%xmm0, 80(%0)\n" + "movntps %%xmm0, 96(%0)\n" + "movntps %%xmm0, 112(%0)\n" + :: "r" (t) : "memory"); + t+=128; + } +#else + __asm__ __volatile__( + "movq (%0), %%mm0\n" + :: "r"(mm_reg):"memory"); + for(; i>0; i--) + { + __asm__ __volatile__ ( + "movntq %%mm0, (%0)\n" + "movntq %%mm0, 8(%0)\n" + "movntq %%mm0, 16(%0)\n" + "movntq %%mm0, 24(%0)\n" + "movntq %%mm0, 32(%0)\n" + "movntq %%mm0, 40(%0)\n" + "movntq %%mm0, 48(%0)\n" + "movntq %%mm0, 56(%0)\n" + "movntq %%mm0, 64(%0)\n" + "movntq %%mm0, 72(%0)\n" + "movntq %%mm0, 80(%0)\n" + "movntq %%mm0, 88(%0)\n" + "movntq %%mm0, 96(%0)\n" + "movntq %%mm0, 104(%0)\n" + "movntq %%mm0, 112(%0)\n" + "movntq %%mm0, 120(%0)\n" + :: "r" (t) : "memory"); + t+=128; + } +#endif /* Have SSE */ +#ifdef HAVE_ASM_MMX2 + /* since movntq is weakly-ordered, a "sfence" + * is needed to become ordered again. */ + __asm__ __volatile__ ("sfence":::"memory"); +#endif +#ifndef HAVE_ASM_SSE + /* enables to use FPU */ + __asm__ __volatile__ ("emms":::"memory"); +#endif + } + /* + * Now do the tail of the block + */ + if(len) small_memset(t, val, len); + return retval; +} + +