diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/audio_dec/xine_dts_decoder.c | 32 | ||||
-rw-r--r-- | src/demuxers/demux_dts.c | 72 | ||||
-rw-r--r-- | src/video_dec/libmpeg2/decode.c | 7 | ||||
-rw-r--r-- | src/xine-engine/xine.c | 74 |
4 files changed, 149 insertions, 36 deletions
diff --git a/src/audio_dec/xine_dts_decoder.c b/src/audio_dec/xine_dts_decoder.c index 2b8dabd10..4f9171d6e 100644 --- a/src/audio_dec/xine_dts_decoder.c +++ b/src/audio_dec/xine_dts_decoder.c @@ -199,19 +199,27 @@ static void dts_decode_frame (dts_decoder_t *this, const int64_t pts, const int audio_buffer->num_frames = this->ac5_pcm_length; - data_out[0] = 0x72; data_out[1] = 0xf8; /* spdif syncword */ - data_out[2] = 0x1f; data_out[3] = 0x4e; /* .............. */ - data_out[4] = ac5_spdif_type; /* DTS data */ - data_out[5] = 0; /* Unknown */ - data_out[6] = (this->ac5_length << 3) & 0xff; /* ac5_length * 8 */ - data_out[7] = ((this->ac5_length ) >> 5) & 0xff; - - if( this->ac5_pcm_length ) { - if( this->ac5_pcm_length % 2) { - swab(data_in, &data_out[8], this->ac5_length ); - } else { - swab(data_in, &data_out[8], this->ac5_length + 1); + // Checking if AC5 data plus IEC958 header will fit into frames samples data + if ( this->ac5_length + 8 <= this->ac5_pcm_length * 2 * 2 ) { + data_out[0] = 0x72; data_out[1] = 0xf8; /* spdif syncword */ + data_out[2] = 0x1f; data_out[3] = 0x4e; /* .............. */ + data_out[4] = ac5_spdif_type; /* DTS data */ + data_out[5] = 0; /* Unknown */ + data_out[6] = (this->ac5_length << 3) & 0xff; /* ac5_length * 8 */ + data_out[7] = ((this->ac5_length ) >> 5) & 0xff; + + if( this->ac5_pcm_length ) { + if( this->ac5_pcm_length % 2) { + swab(data_in, &data_out[8], this->ac5_length ); + } else { + swab(data_in, &data_out[8], this->ac5_length + 1); + } } + // Transmit it without header otherwise, receivers will autodetect DTS + } else { + lprintf("AC5 data is too large (%i > %i), sending without IEC958 header\n", + this->ac5_length + 8, this->ac5_pcm_length * 2 * 2); + memcpy(data_out, data_in, this->ac5_length); } } else { /* Software decode */ diff --git a/src/demuxers/demux_dts.c b/src/demuxers/demux_dts.c index 9d3313a72..750d212f5 100644 --- a/src/demuxers/demux_dts.c +++ b/src/demuxers/demux_dts.c @@ -140,29 +140,63 @@ static int open_dts_file(demux_dts_t *this) { } } + /* DTS bitstream encoding version + * -1 - not detected + * 0 - 16 bits and big endian + * 1 - 16 bits and low endian (detection not implemented) + * 2 - 14 bits and big endian (detection not implemented) + * 3 - 14 bits and low endian + */ + int dts_version = -1; + /* Look for a valid DTS syncword */ for (i=offset; i<peak_size-1; i++) { + /* 16 bits and big endian bitstream */ + if (syncword == 0x7ffe8001) { + dts_version = 0; + break; + } /* 14 bits and little endian bitstream */ - if ((syncword == 0xff1f00e8) && - ((peak[i] & 0xf0) == 0xf0) && (peak[i+1] == 0x07)) { - this->data_start = i-4; - lprintf("found DTS syncword at offset %d\n", i-4); - break; + else if ((syncword == 0xff1f00e8) && + ((peak[i] & 0xf0) == 0xf0) && (peak[i+1] == 0x07)) { + dts_version = 3; + break; } syncword = (syncword << 8) | peak[i]; } + if (dts_version == -1) { + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + LOG_MODULE ": unsupported DTS stream type, or not a DTS stream\n"); + return 0; + } + + this->data_start = i-4; + lprintf("found DTS syncword at offset %d\n", i-4); + if (i < peak_size-9) { unsigned int nblks, fsize, sfreq; + switch (dts_version) + { + case 0: /* BE16 */ + nblks = ((peak[this->data_start+4] & 0x01) << 6) | + ((peak[this->data_start+5] & 0xfc) >> 2); + fsize = (((peak[this->data_start+5] & 0x03) << 12) |(peak[this->data_start+6] << 4) | + ((peak[this->data_start+7] & 0xf0) >> 4)) + 1; + sfreq = (peak[this->data_start+8] & 0x3c) >> 2; + break; - /* 14 bits and little endian bitstream */ - nblks = ((peak[this->data_start+4] & 0x07) << 4) | - ((peak[this->data_start+7] & 0x3c) >> 2); - fsize = (((peak[this->data_start+7] & 0x03) << 12) | - (peak[this->data_start+6] << 4) | - ((peak[this->data_start+9] & 0x3c) >> 2)) + 1; - sfreq = peak[this->data_start+8] & 0x0f; + case 3: /* LE14 */ + nblks = ((peak[this->data_start+4] & 0x07) << 4) | + ((peak[this->data_start+7] & 0x3c) >> 2); + fsize = (((peak[this->data_start+7] & 0x03) << 12) | + (peak[this->data_start+6] << 4) | + ((peak[this->data_start+9] & 0x3c) >> 2)) + 1; + sfreq = peak[this->data_start+8] & 0x0f; + break; + + } if ((sfreq > sizeof(dts_sample_rates)/sizeof(int)) || (dts_sample_rates[sfreq] == 0)) @@ -170,7 +204,19 @@ static int open_dts_file(demux_dts_t *this) { /* Big assumption - this is CBR data */ this->samples_per_frame = (nblks + 1) * 32; - this->frame_size = fsize * 8 / 14 * 2; + + switch (dts_version) + { + case 0: /* BE16 */ + case 1: /* LE16 */ + this->frame_size = fsize * 8 / 16 * 2; + break; + case 2: /* BE14 */ + case 3: /* LE14 */ + this->frame_size = fsize * 8 / 14 * 2; + break; + } + this->sample_rate = dts_sample_rates[sfreq]; lprintf("samples per frame: %d\n", this->samples_per_frame); diff --git a/src/video_dec/libmpeg2/decode.c b/src/video_dec/libmpeg2/decode.c index 145d5f58b..5e70ae1ab 100644 --- a/src/video_dec/libmpeg2/decode.c +++ b/src/video_dec/libmpeg2/decode.c @@ -461,9 +461,10 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, break; case 0xb7: /* sequence end code */ -#ifdef LOG_PAN_SCAN - printf ("libmpeg2: sequence end code not handled\n"); -#endif + mpeg2_flush(mpeg2dec); + mpeg2dec->is_sequence_needed = 1; + break; + case 0xb8: /* group of pictures start code */ if (mpeg2_header_group_of_pictures (picture, buffer)) { printf ("libmpeg2: bad group of pictures\n"); diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index c6dc8a2ce..16d39b2b0 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -1963,11 +1963,12 @@ int xine_get_pos_length (xine_stream_t *stream, int *pos_stream, return 1; } -int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, - int *ratio_code, int *format, - uint8_t *img) { +static int _x_get_current_frame_impl (xine_stream_t *stream, int *width, int *height, + int *ratio_code, int *format, + uint8_t **img, int *size, int alloc_img) { vo_frame_t *frame; + int required_size; stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); frame = stream->video_out->get_last_frame (stream->video_out); @@ -1993,20 +1994,58 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, *format = frame->format; - if (img){ + switch (*format) { + + case XINE_IMGFMT_YV12: + required_size = *width * *height + + ((*width + 1) / 2) * ((*height + 1) / 2) + + ((*width + 1) / 2) * ((*height + 1) / 2); + break; + + case XINE_IMGFMT_YUY2: + required_size = *width * *height + + ((*width + 1) / 2) * *height + + ((*width + 1) / 2) * *height; + break; + + default: + xprintf (stream->xine, XINE_VERBOSITY_DEBUG, + "xine: error, snapshot function not implemented for format 0x%x\n", frame->format); + _x_abort (); + } + + if (alloc_img) { + /* return size if requested */ + if (size) + *size = required_size; + /* allocate img or fail */ + if (!(*img = xine_xmalloc (required_size))) + return 0; + } else { + /* fail if supplied buffer is to small */ + if (*img && size && *size < required_size) { + *size = required_size; + return 0; + } + /* return size if requested */ + if (size) + *size = required_size; + } + + if (*img) { switch (frame->format) { case XINE_IMGFMT_YV12: yv12_to_yv12( /* Y */ frame->base[0], frame->pitches[0], - img, frame->width, + *img, frame->width, /* U */ frame->base[1], frame->pitches[1], - img+frame->width*frame->height, frame->width/2, + *img+frame->width*frame->height, frame->width/2, /* V */ frame->base[2], frame->pitches[2], - img+frame->width*frame->height+frame->width*frame->height/4, frame->width/2, + *img+frame->width*frame->height+frame->width*frame->height/4, frame->width/2, /* width x height */ frame->width, frame->height); break; @@ -2016,7 +2055,7 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, /* src */ frame->base[0], frame->pitches[0], /* dst */ - img, frame->width*2, + *img, frame->width*2, /* width x height */ frame->width, frame->height); break; @@ -2030,6 +2069,25 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, return 1; } +int xine_get_current_frame_alloc (xine_stream_t *stream, int *width, int *height, + int *ratio_code, int *format, + uint8_t **img, int *size) { + uint8_t *no_img = NULL; + return _x_get_current_frame_impl(stream, width, height, ratio_code, format, img ? img : &no_img, size, img != NULL); +} + +int xine_get_current_frame_s (xine_stream_t *stream, int *width, int *height, + int *ratio_code, int *format, + uint8_t *img, int *size) { + return (!img || size) && _x_get_current_frame_impl(stream, width, height, ratio_code, format, &img, size, 0); +} + +int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, + int *ratio_code, int *format, + uint8_t *img) { + return _x_get_current_frame_impl(stream, width, height, ratio_code, format, &img, NULL, 0); +} + int xine_get_video_frame (xine_stream_t *stream, int timestamp, /* msec */ int *width, int *height, |