From: Rocky Bernstein Date: Sun, 4 Jan 2004 16:51:59 +0000 (+0000) Subject: Add OGT and CVD subtitle demuxers. X-Git-Tag: 0.7.1~632 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=f78730a8cc6ad974444fb08e52ad9648d79c5115;p=vlc Add OGT and CVD subtitle demuxers. write_png: might be made into a module and moved elsewhere cvd*: went over documentation a little bit. --- diff --git a/configure.ac b/configure.ac index 14d0a70432..4d12d43d9e 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ dnl Autoconf settings for vlc -dnl $Id: configure.ac,v 1.141 2004/01/04 15:32:13 fenrir Exp $ +dnl $Id: configure.ac,v 1.142 2004/01/04 16:51:59 rocky Exp $ AC_INIT(vlc,0.7.0) @@ -869,8 +869,7 @@ dnl dnl default modules dnl AX_ADD_PLUGINS([dummy rc logger gestures memcpy hotkeys]) -AX_ADD_PLUGINS([mpgv mpga m4v mpeg_system ps ts avi asf aac mp4 rawdv demux2 nsv real]) -AX_ADD_PLUGINS([spudec dvbsub mpeg_audio lpcm a52 dts cinepak]) +AX_ADD_PLUGINS([cvdsub svcdsub spudec dvbsub mpeg_audio lpcm a52 dts cinepak]) AX_ADD_PLUGINS([deinterlace invert adjust wall transform distort clone crop motionblur]) AX_ADD_PLUGINS([float32tos16 float32tos8 float32tou16 float32tou8 a52tospdif dtstospdif fixed32tofloat32 fixed32tos16 s16tofixed32 s16tofloat32 s16tofloat32swab s8tofloat32 u8tofixed32 u8tofloat32]) AX_ADD_PLUGINS([trivial_resampler ugly_resampler linear_resampler bandlimited_resampler]) @@ -2209,7 +2208,10 @@ dnl png dnl AC_CHECK_HEADERS(png.h, [ AX_ADD_LDFLAGS([logo],[-lpng -lz]) - AX_ADD_PLUGINS([logo])]) + AX_ADD_PLUGINS([logo]) + AX_ADD_LDFLAGS([svcdsub],[-lpng -lz]) + AX_ADD_LDFLAGS([cvdsub],[-lpng -lz]) + AC_DEFINE(HAVE_LIBPNG, [], [Define if you have the PNG library: libpng])]) dnl dnl Video plugins @@ -3555,6 +3557,7 @@ AC_CONFIG_FILES([ modules/codec/Makefile modules/codec/ffmpeg/Makefile modules/codec/ffmpeg/postprocessing/Makefile + modules/codec/ogt/Makefile modules/codec/spudec/Makefile modules/control/Makefile modules/control/corba/Makefile diff --git a/doc/subtitles/cvd-subtitles.txt b/doc/subtitles/cvd-subtitles.txt index a116eb3332..aedac44029 100644 --- a/doc/subtitles/cvd-subtitles.txt +++ b/doc/subtitles/cvd-subtitles.txt @@ -1,4 +1,4 @@ -$Id: cvd-subtitles.txt,v 1.1 2004/01/04 16:25:00 rocky Exp $ +$Id: cvd-subtitles.txt,v 1.2 2004/01/04 16:51:59 rocky Exp $ The following information is culled from information from Julio Sanchez Fernandez (http://subhandler.sourceforge.net) by Rocky Bernstein. @@ -18,10 +18,10 @@ subtitle data and the offset to the metadata - i.e. size of the image data plus the four bytes at the beginning. Data for single screen subtitle may come in several non-contiguous -packets of a stream. From the scant data on the format, there is only -only way known to detect the first packet in a subtitle. The first -packet seems to have a valid PTS while later packets for the same -image don't. +packets of a stream. From the scant data on the format, the only way +known to detect the first packet in a subtitle. The first packet +seems to have a valid PTS while later packets for the same image +don't. Image data comes interlaced and is run-length encoded (RLE). Each field is a four-bit nibbles that is further subdivided in a two-bit @@ -56,23 +56,23 @@ code Meaning x = ((p[1]&0x0f)<<6) + (p[2]>>2) y = ((p[2]&0x03)<<8) + p[3]; -0x1f lower right x, y postion, each a 10-bit (0-1023) value, +0x1f lower right x, y position, each a 10-bit (0-1023) value, encoded as above 0x24 3 bytes primary palette 0 - 1 byte for each of y, u, and v -0x25 3 bytes primary palette 1 - 1 byte for each of y, u and v -0x26 3 bytes primary palette 2 - 1 byte for each of y, u and v -0x27 3 bytes primary palette 3 - 1 byte for each of y, u and v +0x25 3 bytes primary palette 1 - 1 byte for each of y, u, and v +0x26 3 bytes primary palette 2 - 1 byte for each of y, u, and v +0x27 3 bytes primary palette 3 - 1 byte for each of y, u, and v 0x2c 3 bytes highlight palette 0 - 1 byte for each of y, u, and v -0x2d 3 bytes highlight palette 1 - 1 byte for each of y, u and v -0x2e 3 bytes highlight palette 2 - 1 byte for each of y, u and v -0x2f 3 bytes highlight palette 3 - 1 byte for each of y, u and v +0x2d 3 bytes highlight palette 1 - 1 byte for each of y, u, and v +0x2e 3 bytes highlight palette 2 - 1 byte for each of y, u, and v +0x2f 3 bytes highlight palette 3 - 1 byte for each of y, u, and v -0x37 3 bytes transparancy for primary palette - 1 byte for each +0x37 3 bytes transparency for primary palette - 1 byte for each of y, u and v -0x3f 3 bytes transparancy for highlight palette - 1 byte for each +0x3f 3 bytes transparency for highlight palette - 1 byte for each of y, u and v 0x47 Offset to start of even rows of interlaced image. diff --git a/modules/codec/ogt/.cvsignore b/modules/codec/ogt/.cvsignore new file mode 100644 index 0000000000..861550933e --- /dev/null +++ b/modules/codec/ogt/.cvsignore @@ -0,0 +1,3 @@ +Makefile +Makefile.am +Makefile.in diff --git a/modules/codec/ogt/Modules.am b/modules/codec/ogt/Modules.am new file mode 100644 index 0000000000..011df4f9b1 --- /dev/null +++ b/modules/codec/ogt/Modules.am @@ -0,0 +1,25 @@ +SOURCES_svcdsub = \ + common.c \ + common.h \ + ogt.c \ + ogt.h \ + subtitle.h \ + ogt_parse.c \ + render.c \ + render.h \ + write_png.c \ + write_png.h \ + $(NULL) + +SOURCES_cvdsub = \ + common.c \ + common.h \ + cvd.c \ + cvd.h \ + subtitle.h \ + cvd_parse.c \ + render.c \ + render.h \ + write_png.c \ + write_png.h \ + $(NULL) diff --git a/modules/codec/ogt/cvd.c b/modules/codec/ogt/cvd.c index 7e3a29ec53..52639dfc42 100644 --- a/modules/codec/ogt/cvd.c +++ b/modules/codec/ogt/cvd.c @@ -2,7 +2,7 @@ * cvd.c : CVD Subtitle decoder thread ***************************************************************************** * Copyright (C) 2003 VideoLAN - * $Id: cvd.c,v 1.7 2004/01/04 04:56:21 rocky Exp $ + * $Id: cvd.c,v 1.8 2004/01/04 16:51:59 rocky Exp $ * * Authors: Rocky Bernstein * based on code from: @@ -182,11 +182,11 @@ Packetize( decoder_t *p_dec, block_t **pp_block ) /***************************************************************************** Reassemble: - The data for single screen subtitle may come in one of many - non-contiguous packets of a stream. This routine is called when the - next packet in the stream comes in. The job of this routine is to - parse the header, if this is the beginning, and combine the packets - into one complete subtitle unit. + Data for single screen subtitle may come in several non-contiguous + packets of a stream. This routine is called when the next packet in + the stream comes in. The job of this routine is to parse the header, + if this is the beginning, and combine the packets into one complete + subtitle unit. If everything is complete, we will return a block. Otherwise return NULL. @@ -225,10 +225,10 @@ Reassemble( decoder_t *p_dec, block_t **pp_block ) if( config_GetInt( p_dec, "spu-channel" ) != p_buffer[0] ) return NULL; - /* There is little data on the format, but it does not seem to have a - good way to detect the first packet in the subtitle. It seems, - however, that it has a valid pts while later packets for the same - image don't */ + /* From the scant data on the format, there is only only way known + to detect the first packet in a subtitle. The first packet + seems to have a valid PTS while later packets for the same + image don't. */ if ( p_sys->state == SUBTITLE_BLOCK_EMPTY && p_block->i_pts == 0 ) { msg_Warn( p_dec, diff --git a/modules/codec/ogt/cvd_parse.c b/modules/codec/ogt/cvd_parse.c index 5af4107265..99a3eca9c5 100644 --- a/modules/codec/ogt/cvd_parse.c +++ b/modules/codec/ogt/cvd_parse.c @@ -2,7 +2,7 @@ * parse.c: Philips OGT (SVCD subtitle) packet parser ***************************************************************************** * Copyright (C) 2003, 2004 VideoLAN - * $Id: cvd_parse.c,v 1.6 2004/01/04 04:56:21 rocky Exp $ + * $Id: cvd_parse.c,v 1.7 2004/01/04 16:51:59 rocky Exp $ * * Authors: Rocky Bernstein * based on code from: @@ -55,12 +55,12 @@ static int ParseImage ( decoder_t *, subpicture_t * ); origin. Thus, this is the result of reading some code whose correctness is not known and some experimentation. - CVD subtitles are different in severl ways from SVCD OGT subtitles. - First, the image comes first and the metadata is at the end. So - that the metadata can be found easily, the subtitle packet starts - with two bytes (everything is big-endian again) that give the total - size of the subtitle data and the offset to the metadata - i.e. size - of the image data plus the four bytes at the beginning. + CVD subtitles are different in several ways from SVCD OGT subtitles. + Image comes first and metadata is at the end. So that the metadata + can be found easily, the subtitle packet starts with two bytes + (everything is big-endian again) that give the total size of the + subtitle data and the offset to the metadata - i.e. size of the + image data plus the four bytes at the beginning. Image data comes interlaced is run-length encoded. Each field is a four-bit nibble. Each nibble contains a two-bit repeat count and a @@ -73,11 +73,6 @@ static int ParseImage ( decoder_t *, subpicture_t * ); that the fill-line complete case above is not as described and the zero repeat count means fill line. The sample code never produces this, so it may be untested. - - The metadata section does not follow a fixed pattern, every - metadata item consists of a tag byte followed by parameters. In all - cases known, the block (including the tag byte) is exactly four - bytes in length. Read the code for the rest. */ void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block ) @@ -108,6 +103,20 @@ void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block ) } +#define ExtractXY(x, y) \ + x = ((p[1]&0x0f)<<6) + (p[2]>>2); \ + y = ((p[2]&0x03)<<8) + p[3]; + + +/* + We parse the metadata information here. + + Although metadata information does not have to come in a fixed field + order, every metadata field consists of a tag byte followed by + parameters. In all cases known, the size including tag byte is + exactly four bytes in length. +*/ + void E_(ParseMetaInfo)( decoder_t *p_dec ) { /* last packet in subtitle block. */ @@ -126,7 +135,7 @@ void E_(ParseMetaInfo)( decoder_t *p_dec ) switch ( p[0] ) { - case 0x04: /* Display duration in 1/90000ths of a second */ + case 0x04: /* subtitle duration in 1/90000ths of a second */ p_sys->i_duration = (p[1]<<16) + (p[2]<<8) + p[3]; @@ -134,25 +143,21 @@ void E_(ParseMetaInfo)( decoder_t *p_dec ) "subtitle display duration %u", p_sys->i_duration); break; - case 0x0c: /* Unknown */ + case 0x0c: /* unknown */ dbg_print( DECODE_DBG_PACKET, "subtitle command unknown 0x%0x 0x%0x 0x%0x 0x%0x\n", p[0], p[1], p[2], p[3]); break; - case 0x17: /* Position */ - p_sys->i_x_start = ((p[1]&0x0f)<<6) + (p[2]>>2); - p_sys->i_y_start = ((p[2]&0x03)<<8) + p[3]; - dbg_print( DECODE_DBG_PACKET, - "start position (%d,%d): %.2x %.2x %.2x", - p_sys->i_x_start, p_sys->i_y_start, - p[1], p[2], p[3] ); + case 0x17: /* coordinates of subtitle upper left x, y position */ + ExtractXY(p_sys->i_x_start, p_sys->i_y_start); break; - case 0x1f: /* Coordinates of the image bottom right */ + case 0x1f: /* coordinates of subtitle bottom right x, y position */ { - int lastx = ((p[1]&0x0f)<<6) + (p[2]>>2); - int lasty = ((p[2]&0x03)<<8) + p[3]; + int lastx; + int lasty; + ExtractXY(lastx, lasty); p_sys->i_width = lastx - p_sys->i_x_start + 1; p_sys->i_height = lasty - p_sys->i_y_start + 1; dbg_print( DECODE_DBG_PACKET, @@ -208,7 +213,7 @@ void E_(ParseMetaInfo)( decoder_t *p_dec ) p_sys->p_palette[3].s.t = p[2] >> 4; dbg_print( DECODE_DBG_PACKET, - "transparancy for primary palette 0..3: " + "transparency for primary palette 0..3: " "0x%0x 0x%0x 0x%0x 0x%0x", p_sys->p_palette[0].s.t, p_sys->p_palette[1].s.t, @@ -225,7 +230,7 @@ void E_(ParseMetaInfo)( decoder_t *p_dec ) p_sys->p_palette_highlight[3].s.t = p[1] >> 4; dbg_print( DECODE_DBG_PACKET, - "transparancy for primary palette 0..3: " + "transparency for primary palette 0..3: " "0x%0x 0x%0x 0x%0x 0x%0x", p_sys->p_palette_highlight[0].s.t, p_sys->p_palette_highlight[1].s.t, @@ -235,8 +240,8 @@ void E_(ParseMetaInfo)( decoder_t *p_dec ) break; case 0x47: - /* offset to first field data, we correct to make it relative - to comp_image_offset (usually 4) */ + /* offset to start of even rows of interlaced image, we correct + to make it relative to comp_image_offset (usually 4) */ p_sys->first_field_offset = (p[2] << 8) + p[3] - p_sys->comp_image_offset; dbg_print( DECODE_DBG_PACKET, @@ -244,8 +249,8 @@ void E_(ParseMetaInfo)( decoder_t *p_dec ) break; case 0x4f: - /* offset to second field data, we correct to make it relative to - comp_image_offset (usually 4) */ + /* offset to start of odd rows of interlaced image, we correct + to make it relative to comp_image_offset (usually 4) */ p_sys->second_field_offset = (p[2] << 8) + p[3] - p_sys->comp_image_offset; dbg_print( DECODE_DBG_PACKET, @@ -309,7 +314,7 @@ E_(ParsePacket)( decoder_t *p_dec) p_spu->i_height = p_sys->i_height; p_spu->i_start = p_sys->i_pts; - p_spu->i_stop = p_sys->i_pts + (p_sys->i_duration * 5); + p_spu->i_stop = p_sys->i_pts + (p_sys->i_duration); p_spu->p_sys->b_crop = VLC_FALSE; p_spu->p_sys->i_debug = p_sys->i_debug; @@ -517,7 +522,6 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu ) } #endif /*HAVE_LIBPNG*/ - VCDInlinePalette( p_dest, p_sys, i_height, i_width ); /* The video is automatically scaled. However subtitle bitmaps diff --git a/modules/codec/ogt/write_png.c b/modules/codec/ogt/write_png.c new file mode 100644 index 0000000000..009044a7ad --- /dev/null +++ b/modules/codec/ogt/write_png.c @@ -0,0 +1,238 @@ +/***************************************************************************** + * Dump an Image to a Portable Network Graphics (PNG) file + **************************************************************************** + Copyright (C) 2004 VideoLAN + Author: Rocky Bernstein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + *****************************************************************************/ + +#include "config.h" +#ifdef HAVE_LIBPNG + +#include +#include +#include "write_png.h" +#include + +typedef void (*snapshot_messenger_t)(char *message); + +#define _(x) x + +/* + * Error functions for use as callbacks by the png libraries + */ + +void error_msg(char *message) +{ + printf("error: %s\n", message); +} + +void warning_msg(char *message) +{ + printf("warning: %s\n", message); +} + +static snapshot_messenger_t error_msg_cb = error_msg; +static snapshot_messenger_t warning_msg_cb = warning_msg; + +static void +user_error_fn(png_structp png_ptr, png_const_charp error_msg) +{ + + if(error_msg_cb) { + char uerror[4096]; + + memset(&uerror, 0, sizeof(uerror)); + sprintf(uerror, _("Error: %s\n"), error_msg); + error_msg_cb(uerror); + } +} + +static void +user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) +{ + if(error_msg_cb) { + char uerror[4096]; + + memset(&uerror, 0, sizeof(uerror)); + sprintf(uerror, _("Error: %s\n"), warning_msg); + warning_msg_cb(uerror); + } +} + +/* + Dump an image to a Portable Network Graphics (PNG) file. File_name + is where the file goes, i_height and i_width are the height and + width in pixels of the image. The data for the image is stored as a + linear array of one byte for each of red, green, and blue + components of an RGB pixel. Thus row[i] will begin at rgb_image + + i*(i_width*3) and the blue pixel at image[i][0] would be rgb_image + + i*(i_width*3) + 1. + + */ +void +write_png(const char *file_name, png_uint_32 i_height, png_uint_32 i_width, + void *rgb_image, /*in*/ png_text *text_ptr, int i_text_count ) +{ + FILE *fp; + png_structp png_ptr; + png_infop info_ptr; + png_color_8 sig_bit; + png_bytep *row_pointers; + + unsigned int i,j; + + /* open the file */ + fp = fopen(file_name, "wb"); + if (fp == NULL) + return; + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible with the one used at compile time, + * in case we are using dynamically linked libraries. REQUIRED. + */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, + user_error_fn, user_warning_fn); + + if (png_ptr == NULL) + { + fclose(fp); + return; + } + + /* Allocate/initialize the image information data. REQUIRED */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + fclose(fp); + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + return; + } + + /* Set error handling. REQUIRED if you aren't supplying your own + * error handling functions in the png_create_write_struct() call. + */ + if (setjmp(png_ptr->jmpbuf)) + { + /* If we get here, we had a problem writing the file */ + fclose(fp); + png_destroy_write_struct(&png_ptr, (png_infopp) &info_ptr); + return; + } + + /* Set up the output control using standard C streams. This + is required. */ + png_init_io(png_ptr, fp); + + /* Set the image information here. i_width and i_height are up to 2^31, + * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on + * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, + * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, + * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or + * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST + * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED + */ + png_set_IHDR(png_ptr, info_ptr, i_width, i_height, 8, PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, + PNG_FILTER_TYPE_BASE); + + /* For color images: */ + sig_bit.red = 8; + sig_bit.green = 8; + sig_bit.blue = 8; + + if (text_ptr) + png_set_text(png_ptr, info_ptr, text_ptr, i_text_count); + + /* Write the file header information. REQUIRED */ + png_write_info(png_ptr, info_ptr); + + /* Once we write out the header, the compression type on the text + * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or + * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again + * at the end. + */ + + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + png_set_shift(png_ptr, &sig_bit); + + /* pack pixels into bytes */ + png_set_packing(png_ptr); + + row_pointers = png_malloc(png_ptr, i_height*sizeof(png_bytep *)); + for (i=0, j=0; i + +/* + Dump an image to a Portable Network Graphics (PNG) file. File_name + is where the file goes, i_height and i_width are the height and + width in pixels of the image. The data for the image is stored as a + linear array RGB pixel entries: one byte for each of red, green, + and blue component. Thus row[i] will begin at rgb_image + + i*(i_width*3) and the blue pixel at image[i][0] would be rgb_image + + i*(i_width*3) + 1. + + text_ptr contains comments that can be written to the image. It can + be null. i_text_count is the number of entries in text_ptr. + + */ +void write_png(const char *file_name, png_uint_32 i_height, + png_uint_32 i_width, void *rgb_image, + /*in*/ png_text *text_ptr, int i_text_count ); +