You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
285 lines
8.6 KiB
285 lines
8.6 KiB
/*****************************************************************************
|
|
* Common SVCD and VCD subtitle routines.
|
|
*****************************************************************************
|
|
* Copyright (C) 2003 VideoLAN
|
|
* $Id: common.c,v 1.1 2003/12/28 04:51:52 rocky Exp $
|
|
*
|
|
* Author: Rocky Bernstein
|
|
* based on code from:
|
|
* Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
|
|
* Samuel Hocevar <sam@zoy.org>
|
|
* Laurent Aimar <fenrir@via.ecp.fr>
|
|
*
|
|
* 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.
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
* Preamble
|
|
*****************************************************************************/
|
|
#include <vlc/vlc.h>
|
|
#include <vlc/vout.h>
|
|
#include <vlc/decoder.h>
|
|
|
|
#include "subtitle.h"
|
|
#include "common.h"
|
|
|
|
/*****************************************************************************
|
|
Free Resources associated with subtitle packet.
|
|
*****************************************************************************/
|
|
void VCDSubClose( vlc_object_t *p_this )
|
|
{
|
|
decoder_t *p_dec = (decoder_t*)p_this;
|
|
decoder_sys_t *p_sys = p_dec->p_sys;
|
|
|
|
dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
|
|
|
|
if( !p_sys->b_packetizer )
|
|
{
|
|
/* FIXME check if it's ok to not lock vout */
|
|
if( p_sys->p_vout != NULL && p_sys->p_vout->p_subpicture != NULL )
|
|
{
|
|
subpicture_t * p_subpic;
|
|
int i_subpic;
|
|
|
|
for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
|
|
{
|
|
p_subpic = &p_sys->p_vout->p_subpicture[i_subpic];
|
|
|
|
if( p_subpic != NULL &&
|
|
( ( p_subpic->i_status == RESERVED_SUBPICTURE ) ||
|
|
( p_subpic->i_status == READY_SUBPICTURE ) ) )
|
|
{
|
|
vout_DestroySubPicture( p_sys->p_vout, p_subpic );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( p_sys->p_block )
|
|
{
|
|
block_ChainRelease( p_sys->p_block );
|
|
}
|
|
|
|
free( p_sys );
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
Initialize so the next packet will start off a new one.
|
|
|
|
*****************************************************************************/
|
|
void
|
|
VCDSubInitSubtitleBlock( decoder_sys_t * p_sys )
|
|
{
|
|
p_sys->i_spu_size = 0;
|
|
p_sys->state = SUBTITLE_BLOCK_EMPTY;
|
|
p_sys->i_spu = 0;
|
|
p_sys->p_block = NULL;
|
|
p_sys->subtitle_data_pos = 0;
|
|
|
|
}
|
|
|
|
void
|
|
VCDSubInitSubtitleData(decoder_sys_t *p_sys)
|
|
{
|
|
if ( p_sys->subtitle_data ) {
|
|
if ( p_sys->subtitle_data_size < p_sys->i_spu_size ) {
|
|
p_sys->subtitle_data = realloc(p_sys->subtitle_data,
|
|
p_sys->i_spu_size);
|
|
p_sys->subtitle_data_size = p_sys->i_spu_size;
|
|
}
|
|
} else {
|
|
p_sys->subtitle_data = malloc(p_sys->i_spu_size);
|
|
p_sys->subtitle_data_size = p_sys->i_spu_size;
|
|
/* FIXME: wrong place to get p_sys */
|
|
p_sys->i_image = 0;
|
|
}
|
|
p_sys->subtitle_data_pos = 0;
|
|
}
|
|
|
|
void
|
|
VCDSubAppendData ( decoder_t *p_dec, uint8_t *buffer, uint32_t buf_len )
|
|
{
|
|
decoder_sys_t *p_sys = p_dec->p_sys;
|
|
int chunk_length = buf_len;
|
|
|
|
if ( chunk_length > p_sys->i_spu_size - p_sys->subtitle_data_pos ) {
|
|
msg_Warn( p_dec, "too much data (%d) expecting at most %u",
|
|
chunk_length, p_sys->i_spu_size - p_sys->subtitle_data_pos );
|
|
|
|
chunk_length = p_sys->i_spu_size - p_sys->subtitle_data_pos;
|
|
}
|
|
|
|
if ( chunk_length > 0 ) {
|
|
memcpy(p_sys->subtitle_data + p_sys->subtitle_data_pos,
|
|
buffer, chunk_length);
|
|
p_sys->subtitle_data_pos += chunk_length;
|
|
dbg_print(DECODE_DBG_PACKET, "%d bytes appended, pointer now %d",
|
|
chunk_length, p_sys->subtitle_data_pos);
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* FindVout: Find a vout or wait for one to be created.
|
|
*****************************************************************************/
|
|
vout_thread_t *VCDSubFindVout( decoder_t *p_dec )
|
|
{
|
|
vout_thread_t *p_vout = NULL;
|
|
|
|
/* Find an available video output */
|
|
do
|
|
{
|
|
if( p_dec->b_die || p_dec->b_error )
|
|
{
|
|
break;
|
|
}
|
|
|
|
p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
|
|
if( p_vout )
|
|
{
|
|
break;
|
|
}
|
|
|
|
msleep( VOUT_OUTMEM_SLEEP );
|
|
}
|
|
while( 1 );
|
|
|
|
return p_vout;
|
|
}
|
|
|
|
|
|
/* Scales down (reduces size) of p_dest in the x direction as
|
|
determined through aspect ratio x_scale by y_scale. Scaling
|
|
is done in place. p_spu->i_width, is updated to new width
|
|
|
|
The aspect ratio is assumed to be between 1/2 and 1.
|
|
*/
|
|
void
|
|
VCDSubScaleX( decoder_t *p_dec, subpicture_t *p_spu,
|
|
unsigned int i_scale_x, unsigned int i_scale_y )
|
|
{
|
|
int i_row, i_col;
|
|
|
|
decoder_sys_t *p_sys = p_dec->p_sys;
|
|
uint8_t *p_src1 = p_spu->p_sys->p_data;
|
|
uint8_t *p_src2 = p_src1 + PIXEL_SIZE;
|
|
uint8_t *p_dst = p_src1;
|
|
unsigned int i_new_width = (p_spu->i_width * i_scale_x) / i_scale_y ;
|
|
unsigned int used=0; /* Number of bytes used up in p_src1. */
|
|
|
|
dbg_print( (DECODE_DBG_CALL|DECODE_DBG_TRANSFORM) ,
|
|
"Old width: %d, new width: %d",
|
|
p_spu->i_width, i_new_width);
|
|
|
|
for ( i_row=0; i_row <= p_spu->i_height - 1; i_row++ ) {
|
|
|
|
if (used != 0) {
|
|
/* Discard the remaining piece of the column of the previous line*/
|
|
used=0;
|
|
p_src1 = p_src2;
|
|
p_src2 += PIXEL_SIZE;
|
|
}
|
|
|
|
for ( i_col=0; i_col <= p_spu->i_width - 2; i_col++ ) {
|
|
unsigned int i;
|
|
unsigned int w1= i_scale_x - used;
|
|
unsigned int w2= i_scale_y - w1;
|
|
|
|
used = w2;
|
|
for (i = 0; i < PIXEL_SIZE; i++ ) {
|
|
*p_dst = ( (*p_src1 * w1) + (*p_src2 * w2) ) / i_scale_y;
|
|
p_src1++; p_src2++; p_dst++;
|
|
}
|
|
|
|
if (i_scale_x == used) {
|
|
/* End of last pixel was end of p_src2. */
|
|
p_src1 = p_src2;
|
|
p_src2 += PIXEL_SIZE;
|
|
i_col++;
|
|
used = 0;
|
|
}
|
|
}
|
|
}
|
|
p_spu->i_width = i_new_width;
|
|
|
|
if ( p_sys && p_sys->i_debug & DECODE_DBG_TRANSFORM )
|
|
{
|
|
ogt_yuvt_t *p_source = (ogt_yuvt_t *) p_spu->p_sys->p_data;
|
|
for ( i_row=0; i_row < p_spu->i_height - 1; i_row++ ) {
|
|
for ( i_col=0; i_col < p_spu->i_width - 1; i_col++ ) {
|
|
printf("%1x", p_source->s.t);
|
|
p_source++;
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* DestroySPU: subpicture destructor
|
|
*****************************************************************************/
|
|
void VCDSubDestroySPU( subpicture_t *p_spu )
|
|
{
|
|
if( p_spu->p_sys->p_input )
|
|
{
|
|
/* Detach from our input thread */
|
|
vlc_object_release( p_spu->p_sys->p_input );
|
|
}
|
|
|
|
vlc_mutex_destroy( &p_spu->p_sys->lock );
|
|
free( p_spu->p_sys );
|
|
}
|
|
|
|
/*****************************************************************************
|
|
This callback is called from the input thread when we need cropping
|
|
*****************************************************************************/
|
|
int VCDSubCropCallback( vlc_object_t *p_object, char const *psz_var,
|
|
vlc_value_t oldval, vlc_value_t newval, void *p_data )
|
|
{
|
|
VCDSubUpdateSPU( (subpicture_t *)p_data, p_object );
|
|
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
update subpicture settings
|
|
*****************************************************************************
|
|
This function is called from CropCallback and at initialization time, to
|
|
retrieve crop information from the input.
|
|
*****************************************************************************/
|
|
void VCDSubUpdateSPU( subpicture_t *p_spu, vlc_object_t *p_object )
|
|
{
|
|
vlc_value_t val;
|
|
|
|
p_spu->p_sys->b_crop = val.b_bool;
|
|
if( !p_spu->p_sys->b_crop )
|
|
{
|
|
return;
|
|
}
|
|
|
|
var_Get( p_object, "x-start", &val );
|
|
p_spu->p_sys->i_x_start = val.i_int;
|
|
var_Get( p_object, "y-start", &val );
|
|
p_spu->p_sys->i_y_start = val.i_int;
|
|
var_Get( p_object, "x-end", &val );
|
|
p_spu->p_sys->i_x_end = val.i_int;
|
|
var_Get( p_object, "y-end", &val );
|
|
p_spu->p_sys->i_y_end = val.i_int;
|
|
|
|
}
|
|
|
|
|