Commit f78730a8 authored by Rocky Bernstein's avatar Rocky Bernstein

Add OGT and CVD subtitle demuxers.

write_png: might be made into a module and moved elsewhere
cvd*: went over documentation a little bit.
parent add4e22d
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
......
$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.
......
Makefile
Makefile.am
Makefile.in
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)
......@@ -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,
......
......@@ -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
......
/*****************************************************************************
* 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 <stdio.h>
#include <stdlib.h>
#include "write_png.h"
#include <setjmp.h>
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<i_height; i++, j+=i_width*3) {
row_pointers[i] = rgb_image + j;
}
png_set_rows (png_ptr, info_ptr, row_pointers);
png_write_image(png_ptr, row_pointers);
/* You can write optional chunks like tEXt, zTXt, and tIME at the end
* as well.
*/
/* It is REQUIRED to call this to finish writing the rest of the file */
png_write_end(png_ptr, info_ptr);
/* if you allocated any text comments, free them here */
/* free image data if allocated. */
/* clean up after the write, and free any memory allocated */
png_destroy_info_struct(png_ptr, &info_ptr);
/* clean up after the write, and free any memory allocated */
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
fclose(fp);
return;
}
#ifdef STANDALONE
int
main(int argc, char **argv)
{
char image_data[3*16 * 3*16 * 3];
int i,j,k,l,m;
char r,g,b,t, or,og,ob;
or=0x00; og=0xFF; ob=0x0;
m=0;
for (i=0; i<3; i++) {
t=or; or=og; og=ob; ob=t;
for (j=0; j<16; j++) {
r=or; g=og; b=ob;
for (k=0; k<3; k++) {
for (l=0; l<16; l++) {
image_data[m++]=r;
image_data[m++]=g;
image_data[m++]=b;
}
t=r; r=g; g=b; b=t;
}
}
}
write_png("/tmp/pngtest.png", 3*16, 3*16, (void *) image_data) ;
return 0;
}
#endif /*STANDALONE*/
#endif /*HAVE_LIBPNG*/
/*****************************************************************************
* 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 <png.h>
/*
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 );
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment