summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--include/xine.h26
-rw-r--r--src/audio_dec/xine_dts_decoder.c32
-rw-r--r--src/demuxers/demux_dts.c72
-rw-r--r--src/video_dec/libmpeg2/decode.c7
-rw-r--r--src/xine-engine/xine.c74
6 files changed, 176 insertions, 37 deletions
diff --git a/ChangeLog b/ChangeLog
index 44fa31445..684811c00 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -72,6 +72,8 @@ xine-lib (1.1.11) unreleased
scripts use xine-lib's automake macros.
* Fixed an off-by-one in the FLAC security fix patch. This breakage was
causing failure to play some files.
+ * Support 16-bit big-endian DTS audio.
+ * Improved frame snapshot API. (ABI extension.)
xine-lib (1.1.10.1) 2008-02-07
* Security fixes:
diff --git a/include/xine.h b/include/xine.h
index 17b8cfbf6..035f4ef7f 100644
--- a/include/xine.h
+++ b/include/xine.h
@@ -401,14 +401,38 @@ int xine_get_param (xine_stream_t *stream, int param) XINE_PROTECTED;
* image format can be YUV 4:2:0 or 4:2:2
* will copy the image data into memory that <img> points to
* (interleaved for yuv 4:2:2 or planary for 4:2:0)
+ *
+ * xine_get_current_frame() requires that <img> must be able
+ * to hold the image data. Use a NULL pointer to retrieve the
+ * necessary parameters for calculating the buffer size. Be
+ * aware that the image can change between two successive calls
+ * so you better pause the stream.
+ *
+ * xine_get_current_frame_s() requires to specify the buffer
+ * size and it returns the needed / used size. It won't copy
+ * image data into a too small buffer.
+ *
+ * xine_get_current_frame_alloc() takes care of allocating
+ * a buffer on it's own, so image data can be retrieved by
+ * a single call without the need to pause the stream.
*
- * returns 1 on success, 0 failure.
+ * all functions return 1 on success, 0 failure.
*/
int xine_get_current_frame (xine_stream_t *stream,
int *width, int *height,
int *ratio_code, int *format,
uint8_t *img) XINE_PROTECTED;
+int xine_get_current_frame_s (xine_stream_t *stream,
+ int *width, int *height,
+ int *ratio_code, int *format,
+ uint8_t *img, int *size) XINE_PROTECTED;
+
+int xine_get_current_frame_alloc (xine_stream_t *stream,
+ int *width, int *height,
+ int *ratio_code, int *format,
+ uint8_t **img, int *size) XINE_PROTECTED;
+
/* xine image formats */
#define XINE_IMGFMT_YV12 (('2'<<24)|('1'<<16)|('V'<<8)|'Y')
#define XINE_IMGFMT_YUY2 (('2'<<24)|('Y'<<16)|('U'<<8)|'Y')
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,