Commit f1c67b56 authored by Derk-Jan Hartman's avatar Derk-Jan Hartman

* VobSub demuxing. Almost working i think, but the ps parsing isn't going to well yet.

  fen, anymore tips? :)
  There seems to be some trouble with bufferoverflows atm and
  spudec doesn't like the data it is being fed:

  [00000199] spudec decoder debug: i_spu_size=8201 i_rle=29701
parent 7c49ef4a
......@@ -2,7 +2,7 @@
* sub.c: subtitle demux for external subtitle files
*****************************************************************************
* Copyright (C) 1999-2004 VideoLAN
* $Id: sub.c,v 1.44 2004/01/26 22:32:51 hartman Exp $
* $Id: sub.c,v 1.45 2004/01/27 07:05:10 hartman Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Derk-Jan Hartman <hartman at videolan dot org>
......@@ -41,6 +41,8 @@
# include <dirent.h>
#endif
#define DVD_VIDEO_LB_LEN 2048
static int Open ( vlc_object_t *p_this );
static int sub_open ( subtitle_demux_t *p_sub,
......@@ -94,6 +96,8 @@ static int Open ( vlc_object_t *p_this )
p_sub->pf_demux = sub_demux;
p_sub->pf_seek = sub_seek;
p_sub->pf_close = sub_close;
ps_track_init( p_sub->tk );
/* Initialize the variables */
var_Create( p_this, "sub-fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
......@@ -210,6 +214,8 @@ static int sub_Vplayer ( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *
static int sub_Sami ( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe );
static int sub_VobSub ( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subtitle, mtime_t i_microsecperframe );
static int DemuxVobSub ( subtitle_demux_t *p_sub, uint8_t *pkt, int i_pkt );
static struct
{
char *psz_type_name;
......@@ -507,20 +513,47 @@ static int sub_demux( subtitle_demux_t *p_sub, mtime_t i_maxdate )
p_sub->i_previously_selected = 0;
return VLC_SUCCESS;
}
if( p_sub->i_sub_type == SUB_TYPE_VOBSUB )
{
off_t filepos = (off_t)p_sub->subtitle[p_sub->i_subtitle].i_vobsub_location;
if( fseeko( p_sub->p_vobsub_file, filepos, SEEK_SET ) )
{
msg_Dbg( p_sub, "Could not seek to vobsublocation: %d", (int)filepos);
}
}
while( p_sub->i_subtitle < p_sub->i_subtitles &&
p_sub->subtitle[p_sub->i_subtitle].i_start < i_maxdate )
{
block_t *p_block;
int i_len;
i_len = strlen( p_sub->subtitle[p_sub->i_subtitle].psz_text ) + 1;
uint8_t packet[DVD_VIDEO_LB_LEN];
int i_len = 0;
if( i_len <= 1 )
if( p_sub->i_sub_type != SUB_TYPE_VOBSUB )
{
/* empty subtitle */
p_sub->i_subtitle++;
continue;
i_len = strlen( p_sub->subtitle[p_sub->i_subtitle].psz_text ) + 1;
if( i_len <= 1 )
{
/* empty subtitle */
p_sub->i_subtitle++;
continue;
}
}
else
{
int i_err = fread( packet, DVD_VIDEO_LB_LEN, 1, p_sub->p_vobsub_file );
if( i_err < 1 )
{
msg_Dbg( p_sub, "could not read vobsub at location: %i", p_sub->subtitle[p_sub->i_subtitle].i_vobsub_location);
p_sub->i_subtitle++;
continue;
}
i_len = ps_pkt_size( packet, DVD_VIDEO_LB_LEN );
if( fseeko( p_sub->p_vobsub_file, i_len, SEEK_CUR ) )
{
msg_Dbg( p_sub, "could not seek to next vobsublocation" );
}
}
if( !( p_block = block_New( p_sub->p_input, i_len ) ) )
......@@ -548,19 +581,31 @@ static int sub_demux( subtitle_demux_t *p_sub, mtime_t i_maxdate )
p_block->i_dts = 0;
}
memcpy( p_block->p_buffer,
if( p_sub->i_sub_type != SUB_TYPE_VOBSUB )
{
memcpy( p_block->p_buffer,
p_sub->subtitle[p_sub->i_subtitle].psz_text, i_len );
if( p_block->i_pts > 0 )
if( p_block->i_pts > 0 )
{
es_out_Send( p_input->p_es_out, p_sub->p_es, p_block );
}
else
{
block_Release( p_block );
}
p_sub->i_subtitle++;
}
else if( i_len > 1 )
{
es_out_Send( p_input->p_es_out, p_sub->p_es, p_block );
memcpy( p_block->p_buffer, packet, i_len );
DemuxVobSub( p_sub, packet, i_len );
}
else
{
block_Release( p_block );
p_sub->i_subtitle++;
}
p_sub->i_subtitle++;
}
return VLC_SUCCESS;
}
......@@ -1074,214 +1119,69 @@ static int sub_VobSub( subtitle_demux_t *p_sub, text_t *txt, subtitle_t *p_subt
fprintf( stderr, "time: %x, location: %x\n", i_start, i_location );
return( 0 );
}
/*
#define mpeg_read(buf, num) _mpeg_read(srcbuf, size, srcpos, buf, num)
static unsigned int _mpeg_read(unsigned char *srcbufunsigned int, unsigned int size,
unsigned int &srcpos, unsigned char *dstbuf,
unsigned int num) {
unsigned int real_num;
if ((srcpos + num) >= size)
real_num = size - srcpos;
else
real_num = num;
memcpy(dstbuf, &srcbuf[srcpos], real_num);
srcpos += real_num;
return real_num;
}
#define mpeg_getc() _mpeg_getch(srcbuf, size, srcpos)
static int _mpeg_getch(unsigned char *srcbuf, unsigned int size,
unsigned int &srcpos) {
unsigned char c;
static int DemuxVobSub( subtitle_demux_t *p_demux, uint8_t *pkt, int i_pkt )
{
uint8_t *p = pkt;
if (mpeg_read(&c, 1) != 1)
return -1;
return (int)c;
}
while( p < &pkt[i_pkt] )
{
int i_size = ps_pkt_size( p, &pkt[i_pkt] - p );
block_t *p_pkt;
if( i_size <= 0 )
{
break;
}
#define mpeg_seek(b, w) _mpeg_seek(size, srcpos, b, w)
static int _mpeg_seek(unsigned int size, unsigned int &srcpos, unsigned int num,
int whence) {
unsigned int new_pos;
if (whence == SEEK_SET)
new_pos = num;
else if (whence == SEEK_CUR)
new_pos = srcpos + num;
else
abort();
if (new_pos >= size) {
srcpos = size;
return 1;
}
srcpos = new_pos;
return 0;
}
/* Create a block */
p_pkt = block_New( p_demux, i_size );
memcpy( p_pkt->p_buffer, p, i_size);
#define mpeg_tell() srcpos
*/
/*
static int mpeg_run(demuxer_t *demuxer, unsigned char *srcbuf, unsigned int size) {
unsigned int len, idx, version, srcpos, packet_size;
int c, aid;
float pts;*/
/* Goto start of a packet, it starts with 0x000001?? */
/*const unsigned char wanted[] = { 0, 0, 1 };
unsigned char buf[5];
demux_packet_t *dp;
demux_stream_t *ds;
mkv_demuxer_t *mkv_d;
mkv_d = (mkv_demuxer_t *)demuxer->priv;
ds = demuxer->sub;
srcpos = 0;
packet_size = 0;
while (1) {
if (mpeg_read(buf, 4) != 4)
return -1;
while (memcmp(buf, wanted, sizeof(wanted)) != 0) {
c = mpeg_getc();
if (c < 0)
return -1;
memmove(buf, buf + 1, 3);
buf[3] = c;
}
switch (buf[3]) {
case 0xb9: */ /* System End Code */
/* return 0;
break;
case 0xba: */ /* Packet start code */
/* c = mpeg_getc();
if (c < 0)
return -1;
if ((c & 0xc0) == 0x40)
version = 4;
else if ((c & 0xf0) == 0x20)
version = 2;
else {
mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] VobSub: Unsupported MPEG "
"version: 0x%02x\n", c);
return -1;
}
/* Parse it and send it */
switch( 0x100 | p[3] )
{
case 0x1b9:
case 0x1bb:
case 0x1bc:
msg_Dbg( p_demux, "we don't need these ps packets" );
block_Release( p_pkt );
break;
if (version == 4) {
if (mpeg_seek(9, SEEK_CUR))
return -1;
} else if (version == 2) {
if (mpeg_seek(7, SEEK_CUR))
return -1;
} else
abort();
break;
case 0xbd: */ /* packet */
/* if (mpeg_read(buf, 2) != 2)
return -1;
len = buf[0] << 8 | buf[1];
idx = mpeg_tell();
c = mpeg_getc();
if (c < 0)
return -1;
if ((c & 0xC0) == 0x40) {*/ /* skip STD scale & size */
/* if (mpeg_getc() < 0)
return -1;
c = mpeg_getc();
if (c < 0)
return -1;
}
if ((c & 0xf0) == 0x20) { */ /* System-1 stream timestamp */
/* Do we need this? */
/* abort();
} else if ((c & 0xf0) == 0x30) {
*/ /* Do we need this? */
/* abort();
} else if ((c & 0xc0) == 0x80) {*/ /* System-2 (.VOB) stream */
/* unsigned int pts_flags, hdrlen, dataidx;
c = mpeg_getc();
if (c < 0)
return -1;
pts_flags = c;
c = mpeg_getc();
if (c < 0)
return -1;
hdrlen = c;
dataidx = mpeg_tell() + hdrlen;
if (dataidx > idx + len) {
mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] VobSub: Invalid header "
"length: %d (total length: %d, idx: %d, dataidx: %d)\n",
hdrlen, len, idx, dataidx);
return -1;
}
if ((pts_flags & 0xc0) == 0x80) {
if (mpeg_read(buf, 5) != 5)
return -1;
if (!(((buf[0] & 0xf0) == 0x20) && (buf[0] & 1) && (buf[2] & 1) &&
(buf[4] & 1))) {
mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] VobSub PTS error: 0x%02x "
"%02x%02x %02x%02x \n",
buf[0], buf[1], buf[2], buf[3], buf[4]);
pts = 0;
} else
pts = ((buf[0] & 0x0e) << 29 | buf[1] << 22 |
(buf[2] & 0xfe) << 14 | buf[3] << 7 | (buf[4] >> 1));
} else*/ /* if ((pts_flags & 0xc0) == 0xc0) */// {
/* what's this? */
/* abort(); */
/* }
mpeg_seek(dataidx, SEEK_SET);
aid = mpeg_getc();
if (aid < 0) {
mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] VobSub: Bogus aid %d\n", aid);
return -1;
}
packet_size = len - ((unsigned int)mpeg_tell() - idx);
dp = new_demux_packet(packet_size);
dp->flags = 1;
dp->pts = mkv_d->last_pts;
if (mpeg_read(dp->buffer, packet_size) != packet_size) {
mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] VobSub: mpeg_read failure");
packet_size = 0;
return -1;
}
ds_add_packet(ds, dp);
idx = len;
case 0x1ba:
{
msg_Dbg( p_demux, "pack: we don't need the info" );
block_Release( p_pkt );
break;
}
break;
case 0xbe: */ /* Padding */
/* if (mpeg_read(buf, 2) != 2)
return -1;
len = buf[0] << 8 | buf[1];
if ((len > 0) && mpeg_seek(len, SEEK_CUR))
return -1;
break;
default:
if ((0xc0 <= buf[3]) && (buf[3] < 0xf0)) {
*/ /* MPEG audio or video */
/* if (mpeg_read(buf, 2) != 2)
return -1;
len = (buf[0] << 8) | buf[1];
if ((len > 0) && mpeg_seek(len, SEEK_CUR))
return -1;
default:
{
int i_id = ps_pkt_id( p_pkt );
msg_Dbg( p_demux, "do we have a spu pes ? that would be so cool" );
if( i_id >= 0xc0 )
{
ps_track_t *tk = &p_demux->tk[PS_ID_TO_TK(i_id)];
if( p_demux->p_es &&
!ps_pkt_parse_pes( p_pkt, tk->i_skip ) )
{
msg_Dbg( p_demux, "do we pass it along?" );
es_out_Send( p_demux->p_input->p_es_out, p_demux->p_es, p_pkt );
}
else
{
block_Release( p_pkt );
}
}
else
{
block_Release( p_pkt );
}
break;
}
else {
mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] VobSub: unknown header "
"0x%02X%02X%02X%02X\n", buf[0], buf[1], buf[2], buf[3]);
return -1;
}
p += i_size;
}
}
return 0;
return VLC_SUCCESS;
}
*/
......@@ -2,7 +2,7 @@
* sub.h
*****************************************************************************
* Copyright (C) 2001-2004 VideoLAN
* $Id: sub.h,v 1.16 2004/01/26 22:42:50 hartman Exp $
* $Id: sub.h,v 1.17 2004/01/27 07:05:10 hartman Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -21,6 +21,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#include "../ps.h"
#define SUB_TYPE_MICRODVD 0x00
#define SUB_TYPE_SUBRIP 0x01
#define SUB_TYPE_SSA1 0x02
......@@ -65,6 +67,7 @@ typedef struct subtitle_demux_s
es_out_id_t *p_es;
int i_previously_selected; /* to make pf_seek */
FILE *p_vobsub_file;
ps_track_t *tk[PS_TK_COUNT];
} subtitle_demux_t;
......
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