/*****************************************************************************
* Common SVCD and VCD subtitle routines.
*****************************************************************************
- * Copyright (C) 2003 VideoLAN
- * $Id: common.c,v 1.2 2003/12/30 04:43:52 rocky Exp $
+ * Copyright (C) 2003, 2004 VideoLAN
+ * $Id: common.c,v 1.3 2004/01/03 12:54:56 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
#include "subtitle.h"
#include "common.h"
+#ifdef HAVE_LIBPNG
+#include "write_png.h"
+#endif
/*****************************************************************************
Free Resources associated with subtitle packet.
}
if ( chunk_length > 0 ) {
+#if 0
+ int i;
+ int8_t *b=buffer;
+ for (i=0; i<chunk_length; i++)
+ printf ("%02x", b[i]);
+ printf("\n");
+#endif
+
memcpy(p_sys->subtitle_data + p_sys->subtitle_data_pos,
buffer, chunk_length);
p_sys->subtitle_data_pos += chunk_length;
ogt_yuvt_t *p_to = (ogt_yuvt_t *) p_dest;
for ( ; n >= 0 ; n-- ) {
- p_to[n] = p_sys->pi_palette[p_from[n]];
+ p_to[n] = p_sys->p_palette[p_from[n]];
}
}
}
+/*
+ Dump an a subtitle image to standard output - for debugging.
+ */
+void VCDSubDumpImage( uint8_t *p_image, uint32_t i_height, uint32_t i_width )
+{
+ uint8_t *p = p_image;
+ unsigned int i_row; /* scanline row number */
+ unsigned int i_column; /* scanline column number */
+
+ printf("-------------------------------------\n++");
+ for ( i_row=0; i_row < i_height; i_row ++ ) {
+ for ( i_column=0; i_column<i_width; i_column++ ) {
+ printf("%1d", *p++ & 0x03);
+ }
+ printf("\n++");
+ }
+ printf("\n-------------------------------------\n");
+}
+
+/*
+ FIXME:
+ MOVE clip_8_bit and uuv2rgb TO A MORE GENERIC PLACE.
+ */
+
+/* Force v in the range 0.255 */
+static inline uint8_t
+clip_8_bit(int v)
+{
+ if (v<0) return 0;
+ if (v>255) return 255;
+ return (uint8_t) v;
+}
+
+/***************************************************
+ Color conversion from
+ http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html#RTFToC30
+ http://people.ee.ethz.ch/~buc/brechbuehler/mirror/color/ColorFAQ.html
+
+ Thanks to Billy Biggs <vektor@dumbterm.net> for the pointer and
+ the following conversion.
+
+ R' = [ 1.1644 0 1.5960 ] ([ Y' ] [ 16 ])
+ G' = [ 1.1644 -0.3918 -0.8130 ] * ([ Cb ] - [ 128 ])
+ B' = [ 1.1644 2.0172 0 ] ([ Cr ] [ 128 ])
+
+ See also vlc/modules/video_chroma/i420_rgb.h and
+ vlc/modules/video_chroma/i420_rgb_c.h for a way to do this in a way
+ more optimized for integer arithmetic. Would be nice to merge the
+ two routines.
+
+***************************************************/
+
+static inline void
+yuv2rgb(ogt_yuvt_t *p_yuv, uint8_t *p_rgb_out )
+{
+
+ int i_Y = p_yuv->s.y - 16;
+ int i_Cb = p_yuv->s.v - 128;
+ int i_Cr = p_yuv->s.u - 128;
+
+ int i_red = (1.1644 * i_Y) + (1.5960 * i_Cr);
+ int i_green = (1.1644 * i_Y) - (0.3918 * i_Cb) - (0.8130 * i_Cr);
+ int i_blue = (1.1644 * i_Y) + (2.0172 * i_Cb);
+
+ i_red = clip_8_bit( i_red );
+ i_green = clip_8_bit( i_green );
+ i_blue = clip_8_bit( i_blue );
+
+ *p_rgb_out++ = i_red;
+ *p_rgb_out++ = i_green;
+ *p_rgb_out++ = i_blue;
+
+}
+
+#ifdef HAVE_LIBPNG
+
+#define BYTES_PER_RGB 3
+#define PALETTE_SIZE 4
+/* Note the below assumes the above is a power of 2 */
+#define PALETTE_SIZE_MASK (PALETTE_SIZE-1)
+
+/*
+ Dump an a subtitle image to a Portable Network Graphics (PNG) file.
+ All we do here is convert YUV palette entries to RGB, expand
+ the image into a linear RGB pixel array, and call the routine
+ that does the PNG writing.
+ */
+
+void
+VCDSubDumpPNG( uint8_t *p_image, decoder_t *p_dec,
+ uint32_t i_height, uint32_t i_width, const char *filename,
+ png_text *text_ptr, int i_text_count )
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ uint8_t *p = p_image;
+ uint8_t *image_data = malloc(BYTES_PER_RGB * i_height * i_width );
+ uint8_t *q = image_data;
+ unsigned int i_row; /* scanline row number */
+ unsigned int i_column; /* scanline column number */
+ uint8_t rgb_palette[PALETTE_SIZE * BYTES_PER_RGB];
+ int i;
+
+ dbg_print( (DECODE_DBG_CALL), "%s", filename);
+
+ if (NULL == image_data) return;
+
+ /* Convert palette YUV into RGB. */
+ for (i=0; i<PALETTE_SIZE; i++) {
+ ogt_yuvt_t *p_yuv = &(p_sys->p_palette[i]);
+ uint8_t *p_rgb_out = &(rgb_palette[i*BYTES_PER_RGB]);
+ yuv2rgb( p_yuv, p_rgb_out );
+ }
+
+ /* Convert palette entries into linear RGB array. */
+ for ( i_row=0; i_row < i_height; i_row ++ ) {
+ for ( i_column=0; i_column<i_width; i_column++ ) {
+ uint8_t *p_rgb = &rgb_palette[ ((*p)&PALETTE_SIZE_MASK)*BYTES_PER_RGB ];
+ *q++ = p_rgb[0];
+ *q++ = p_rgb[1];
+ *q++ = p_rgb[2];
+ p++;
+ }
+ }
+
+ write_png( filename, i_height, i_width, image_data, text_ptr, i_text_count );
+ free(image_data);
+}
+#endif /*HAVE_LIBPNG*/
/*****************************************************************************
* Header for Common SVCD and VCD subtitle routines.
*****************************************************************************
- * Copyright (C) 2003 VideoLAN
- * $Id: common.h,v 1.2 2003/12/30 04:43:52 rocky Exp $
+ * Copyright (C) 2003, 2004 VideoLAN
+ * $Id: common.h,v 1.3 2004/01/03 12:54:56 rocky Exp $
*
* Author: Rocky Bernstein
*
*****************************************************************************/
void VCDSubClose ( vlc_object_t * );
+
void VCDSubInitSubtitleBlock( decoder_sys_t * p_sys );
+
void VCDSubInitSubtitleData(decoder_sys_t *p_sys);
+
void VCDSubAppendData( decoder_t *p_dec, uint8_t *buffer,
uint32_t buf_len );
vout_thread_t *VCDSubFindVout( decoder_t *p_dec );
void VCDSubScaleX( decoder_t *p_dec, subpicture_t *p_spu,
unsigned int i_scale_x, unsigned int i_scale_y );
+
void VCDSubDestroySPU( subpicture_t *p_spu );
+
int VCDSubCropCallback( vlc_object_t *p_object, char const *psz_var,
vlc_value_t oldval, vlc_value_t newval,
void *p_data );
+
void VCDSubUpdateSPU( subpicture_t *p_spu, vlc_object_t *p_object );
+
void VCDInlinePalette ( /*inout*/ uint8_t *p_dest,
decoder_sys_t *p_sys, unsigned int i_height,
unsigned int i_width );
+void VCDSubDumpImage( uint8_t *p_image, uint32_t i_height,
+ uint32_t i_width );
-
+#ifdef HAVE_LIBPNG
+#include <png.h>
+void VCDSubDumpPNG( uint8_t *p_image, decoder_t *p_dec,
+ uint32_t i_height, uint32_t i_width,
+ const char *filename, /*in*/ png_text *text_ptr,
+ int i_text_count );
+#endif /*HAVE_LIBPNG*/
* cvd.c : CVD Subtitle decoder thread
*****************************************************************************
* Copyright (C) 2003 VideoLAN
- * $Id: cvd.c,v 1.5 2004/01/01 13:54:24 rocky Exp $
+ * $Id: cvd.c,v 1.6 2004/01/03 12:54:56 rocky Exp $
*
* Authors: Rocky Bernstein
* based on code from:
#include "cvd.h"
#include "common.h"
-#define DEBUG_LONGTEXT N_( \
- "This integer when viewed in binary is a debugging mask\n" \
- "external call 1\n" \
- "all calls 2\n" \
- "packet assembly info 4\n" \
- "image bitmaps 8\n" \
- "image transformations 16\n" \
- "misc info 32\n" )
-
/*****************************************************************************
* Module descriptor.
*****************************************************************************/
"primary palette %d (y,u,v): (0x%0x,0x%0x,0x%0x)",
v, p[1], p[2], p[3]);
- p_sys->pi_palette[v].s.y = p[1];
- p_sys->pi_palette[v].s.u = p[2];
- p_sys->pi_palette[v].s.v = p[3];
+ p_sys->p_palette[v].s.y = p[1];
+ p_sys->p_palette[v].s.u = p[2];
+ p_sys->p_palette[v].s.v = p[3];
break;
}
v, p[1], p[2], p[3]);
/* Highlight Palette */
- p_sys->pi_palette_highlight[v].s.y = p[1];
- p_sys->pi_palette_highlight[v].s.u = p[2];
- p_sys->pi_palette_highlight[v].s.v = p[3];
+ p_sys->p_palette_highlight[v].s.y = p[1];
+ p_sys->p_palette_highlight[v].s.u = p[2];
+ p_sys->p_palette_highlight[v].s.v = p[3];
break;
}
case 0x37:
/* transparency for primary palette */
- p_sys->pi_palette[0].s.t = p[3] & 0x0f;
- p_sys->pi_palette[1].s.t = p[3] >> 4;
- p_sys->pi_palette[2].s.t = p[2] & 0x0f;
- p_sys->pi_palette[3].s.t = p[2] >> 4;
+ p_sys->p_palette[0].s.t = p[3] & 0x0f;
+ p_sys->p_palette[1].s.t = p[3] >> 4;
+ p_sys->p_palette[2].s.t = p[2] & 0x0f;
+ p_sys->p_palette[3].s.t = p[2] >> 4;
dbg_print( DECODE_DBG_PACKET,
"transparancy for primary palette 0..3: "
"0x%0x 0x%0x 0x%0x 0x%0x",
- p_sys->pi_palette[0].s.t,
- p_sys->pi_palette[1].s.t,
- p_sys->pi_palette[2].s.t,
- p_sys->pi_palette[3].s.t );
+ p_sys->p_palette[0].s.t,
+ p_sys->p_palette[1].s.t,
+ p_sys->p_palette[2].s.t,
+ p_sys->p_palette[3].s.t );
break;
case 0x3f:
/* transparency for highlight palette */
- p_sys->pi_palette_highlight[0].s.t = p[2] & 0x0f;
- p_sys->pi_palette_highlight[1].s.t = p[2] >> 4;
- p_sys->pi_palette_highlight[2].s.t = p[1] & 0x0f;
- p_sys->pi_palette_highlight[3].s.t = p[1] >> 4;
+ p_sys->p_palette_highlight[0].s.t = p[2] & 0x0f;
+ p_sys->p_palette_highlight[1].s.t = p[2] >> 4;
+ p_sys->p_palette_highlight[2].s.t = p[1] & 0x0f;
+ p_sys->p_palette_highlight[3].s.t = p[1] >> 4;
dbg_print( DECODE_DBG_PACKET,
"transparancy for primary palette 0..3: "
"0x%0x 0x%0x 0x%0x 0x%0x",
- p_sys->pi_palette_highlight[0].s.t,
- p_sys->pi_palette_highlight[1].s.t,
- p_sys->pi_palette_highlight[2].s.t,
- p_sys->pi_palette_highlight[3].s.t );
+ p_sys->p_palette_highlight[0].s.t,
+ p_sys->p_palette_highlight[1].s.t,
+ p_sys->p_palette_highlight[2].s.t,
+ p_sys->p_palette_highlight[3].s.t );
break;
/*****************************************************************************
* parse.c: Philips OGT (SVCD subtitle) packet parser
*****************************************************************************
- * Copyright (C) 2003 VideoLAN
- * $Id: cvd_parse.c,v 1.4 2003/12/30 04:43:52 rocky Exp $
+ * Copyright (C) 2003, 2004 VideoLAN
+ * $Id: cvd_parse.c,v 1.5 2004/01/03 12:54:56 rocky Exp $
*
* Authors: Rocky Bernstein
* based on code from:
#include "cvd.h"
#include "common.h"
+#ifdef HAVE_LIBPNG
+#include <png.h>
+#endif
+
/* An image color is a two-bit palette entry: 0..3 */
typedef uint8_t ogt_color_t;
for ( i_field=0; i_field < 2; i_field++ ) {
i_nibble_field = 2; /* 4-bit pieces available in *p */
+#if 0
+ unsigned int i;
+ int8_t *b=p;
+ for (i=0; i< i_width * i_height; i++)
+ printf ("%02x", b[i]);
+ printf("\n");
+#endif
+
for ( i_row=i_field; i_row < i_height; i_row += 2 ) {
b_filling = VLC_FALSE;
for ( i_column=0; i_column<i_width; i_column++ ) {
}
}
- /* Dump out image not interlaced... */
- if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE) {
- uint8_t *p = p_dest;
- printf("-------------------------------------\n++");
- for ( i_row=0; i_row < i_height; i_row ++ ) {
- for ( i_column=0; i_column<i_width; i_column++ ) {
- printf("%1d", *p++ & 0x03);
- }
- printf("\n++");
- }
- printf("\n-------------------------------------\n");
+ if (p_sys && (p_sys->i_debug & DECODE_DBG_IMAGE)) {
+ /* Dump out image not interlaced... */
+ VCDSubDumpImage( p_dest, i_height, i_width );
+ }
+
+#ifdef HAVE_LIBPNG
+ if (p_sys && (p_sys->i_debug & DECODE_DBG_PNG)) {
+#define TEXT_COUNT 2
+ /* Dump image to a file in PNG format. */
+ char filename[300];
+ png_text text_ptr[TEXT_COUNT];
+
+ text_ptr[0].key = "Preparer";
+ text_ptr[0].text = "VLC";
+ text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
+ text_ptr[1].key = "Description";
+ text_ptr[1].text = "CVD Subtitle";
+ text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
+
+ snprintf(filename, 300, "%s%d.png", "/tmp/vlc-cvd-sub", p_sys->i_image);
+ VCDSubDumpPNG( p_dest, p_dec, i_height, i_width, filename,
+ text_ptr, TEXT_COUNT );
}
+#endif /*HAVE_LIBPNG*/
+
VCDInlinePalette( p_dest, p_sys, i_height, i_width );
/*****************************************************************************
* ogt.c : Overlay Graphics Text (SVCD subtitles) decoder thread
*****************************************************************************
- * Copyright (C) 2003 VideoLAN
- * $Id: ogt.c,v 1.7 2004/01/01 13:55:17 rocky Exp $
+ * Copyright (C) 2003, 2004 VideoLAN
+ * $Id: ogt.c,v 1.8 2004/01/03 12:54:56 rocky Exp $
*
- * Authors: Rocky Bernstein
+ * Author: Rocky Bernstein
* based on code from:
* Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
* Samuel Hocevar <sam@zoy.org>
#include "ogt.h"
#include "common.h"
-#define DEBUG_LONGTEXT N_( \
- "This integer when viewed in binary is a debugging mask\n" \
- "external call 1\n" \
- "all calls 2\n" \
- "packet assembly info 4\n" \
- "image bitmaps 8\n" \
- "image transformations 16\n" \
- "rendering information 32\n" \
- "misc info 64\n" )
-
-
/*****************************************************************************
* Module descriptor.
*****************************************************************************/
/*****************************************************************************
* Philips OGT (SVCD subtitle) packet parser
*****************************************************************************
- * Copyright (C) 2003 VideoLAN
- * $Id: ogt_parse.c,v 1.4 2003/12/30 04:43:52 rocky Exp $
+ * Copyright (C) 2003, 2004 VideoLAN
+ * $Id: ogt_parse.c,v 1.5 2004/01/03 12:54:56 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
#include "render.h"
#include "ogt.h"
+#ifdef HAVE_LIBPNG
+#include <png.h>
+#endif
+
/* An image color is a two-bit palette entry: 0..3 */
typedef uint8_t ogt_color_t;
p_sys->i_height = GETINT16(p);
for (i=0; i<4; i++) {
- p_sys->pi_palette[i].s.y = *p++;
- p_sys->pi_palette[i].s.u = *p++;
- p_sys->pi_palette[i].s.v = *p++;
+ p_sys->p_palette[i].s.y = *p++;
+ p_sys->p_palette[i].s.u = *p++;
+ p_sys->p_palette[i].s.v = *p++;
/* OGT has 8-bit resolution for alpha, but DVD's and CVDS use 4-bits.
Since we want to use the same render routine, rather than scale up
CVD (and DVD) subtitles, we'll scale down ours.
*/
- p_sys->pi_palette[i].s.t = (*p++) >> 4;
+ p_sys->p_palette[i].s.t = (*p++) >> 4;
}
p_sys->i_cmd = *p++;
/* We do not really know this, FIXME */
for (i=0; i<4; i++) {
msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
- p_sys->pi_palette[i].s.t, p_sys->pi_palette[i].s.y,
- p_sys->pi_palette[i].s.u, p_sys->pi_palette[i].s.v );
+ p_sys->p_palette[i].s.t, p_sys->p_palette[i].s.y,
+ p_sys->p_palette[i].s.u, p_sys->p_palette[i].s.v );
}
}
}
}
- if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)
+ if (p_sys && (p_sys->i_debug & DECODE_DBG_IMAGE))
printf("\n");
if ( i_2bit_field != 4 ) {
+ p_sys->second_field_offset;
}
- /* Dump out image not interlaced... */
- if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE) {
- uint8_t *p = p_dest;
- printf("-------------------------------------\n++");
- for ( i_row=0; i_row < i_height; i_row ++ ) {
- for ( i_column=0; i_column<i_width; i_column++ ) {
- printf("%1d", *p++ & 0x03);
- }
- printf("\n++");
- }
- printf("\n-------------------------------------\n");
+ if (p_sys && (p_sys->i_debug & DECODE_DBG_IMAGE)) {
+ /* Dump out image not interlaced... */
+ VCDSubDumpImage( p_dest, i_height, i_width );
}
+#ifdef HAVE_LIBPNG
+ if (p_sys && (p_sys->i_debug & DECODE_DBG_PNG)) {
+#define TEXT_COUNT 2
+ /* Dump image to a file in PNG format. */
+ char filename[300];
+ png_text text_ptr[TEXT_COUNT];
+
+ text_ptr[0].key = "Preparer";
+ text_ptr[0].text = "VLC";
+ text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
+ text_ptr[1].key = "Description";
+ text_ptr[1].text = "SVCD Subtitle";
+ text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
+
+ snprintf(filename, 300, "%s%d.png", "/tmp/vlc-svcd-sub", p_sys->i_image);
+ VCDSubDumpPNG( p_dest, p_dec, i_height, i_width, filename,
+ text_ptr, TEXT_COUNT );
+ }
+#endif /*HAVE_LIBPNG*/
+
VCDInlinePalette( p_dest, p_sys, i_height, i_width );
+
/* The video is automatically scaled. However subtitle bitmaps
assume a 1:1 aspect ratio. So we need to scale to compensate for
/*****************************************************************************
* subtitle.h : Common SVCD and CVD subtitles header
*****************************************************************************
- * Copyright (C) 2003 VideoLAN
- * $Id: subtitle.h,v 1.2 2003/12/28 11:26:52 rocky Exp $
+ * Copyright (C) 2003,2004 VideoLAN
+ * $Id: subtitle.h,v 1.3 2004/01/03 12:54:56 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
#define DECODE_DBG_IMAGE 8 /* image bitmaps */
#define DECODE_DBG_TRANSFORM 16 /* bitmap transformations */
#define DECODE_DBG_RENDER 32 /* rendering information */
-#define DECODE_DBG_INFO 64
+#define DECODE_DBG_PNG 64 /* Extract subtitles to PNG files. */
+#define DECODE_DBG_INFO 128
+
+#define DEBUG_LONGTEXT N_( \
+ "This integer when viewed in binary is a debugging mask\n" \
+ "external call 1\n" \
+ "all calls 2\n" \
+ "packet assembly info 4\n" \
+ "image bitmaps 8\n" \
+ "image transformations 16\n" \
+ "rendering information 32\n" \
+ "extract subtitles 64\n" \
+ "misc info 128\n" )
#define DECODE_DEBUG 1
#if DECODE_DEBUG
image when displayed */
uint16_t i_width, i_height; /* dimensions in pixels of image */
- ogt_yuvt_t pi_palette[NUM_SUBTITLE_COLORS]; /* Palette of colors used
+ ogt_yuvt_t p_palette[NUM_SUBTITLE_COLORS]; /* Palette of colors used
in subtitle */
- ogt_yuvt_t pi_palette_highlight[NUM_SUBTITLE_COLORS]; /* Only used
+ ogt_yuvt_t p_palette_highlight[NUM_SUBTITLE_COLORS]; /* Only used
for CVD */
uint8_t i_options;