/*****************************************************************************
* es_format.c : es_format_t helpers.
*****************************************************************************
* Copyright (C) 2008 the VideoLAN team
* $Id$
*
* Author: Laurent Aimar <fenrir@videolan.org>
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "vlc_common.h"
#include "vlc_es.h"
/*****************************************************************************
* BinaryLog: computes the base 2 log of a binary value
*****************************************************************************
* This functions is used by MaskToShift, to get a bit index from a binary
* value.
*****************************************************************************/
static int BinaryLog( uint32_t i )
{
int i_log = 0;
if( i == 0 ) return -31337;
if( i & 0xffff0000 ) i_log += 16;
if( i & 0xff00ff00 ) i_log += 8;
if( i & 0xf0f0f0f0 ) i_log += 4;
if( i & 0xcccccccc ) i_log += 2;
if( i & 0xaaaaaaaa ) i_log += 1;
return i_log;
}
/**
* It transforms a color mask into right and left shifts
* FIXME copied from video_output.c
*/
static void MaskToShift( int *pi_left, int *pi_right, uint32_t i_mask )
{
uint32_t i_low, i_high; /* lower hand higher bits of the mask */
if( !i_mask )
{
*pi_left = *pi_right = 0;
return;
}
/* Get bits */
i_low = i_high = i_mask;
i_low &= - (int32_t)i_low; /* lower bit of the mask */
i_high += i_low; /* higher bit of the mask */
/* Transform bits into an index. Also deal with i_high overflow, which
* is faster than changing the BinaryLog code to handle 64 bit integers. */
i_low = BinaryLog (i_low);
i_high = i_high ? BinaryLog (i_high) : 32;
/* Update pointers and return */
*pi_left = i_low;
*pi_right = (8 - i_high + i_low);
}
/* */
void video_format_FixRgb( video_format_t *p_fmt )
{
/* FIXME find right default mask */
if( !p_fmt->i_rmask || !p_fmt->i_gmask || !p_fmt->i_bmask )
{
switch( p_fmt->i_chroma )
{
case VLC_FOURCC('R','V','1','5'):
p_fmt->i_rmask = 0x7c00;
p_fmt->i_gmask = 0x03e0;
p_fmt->i_bmask = 0x001f;
break;
case VLC_FOURCC('R','V','1','6'):
p_fmt->i_rmask = 0xf800;
p_fmt->i_gmask = 0x07e0;
p_fmt->i_bmask = 0x001f;
break;
case VLC_FOURCC('R','V','2','4'):
p_fmt->i_rmask = 0xff0000;
p_fmt->i_gmask = 0x00ff00;
p_fmt->i_bmask = 0x0000ff;
break;
case VLC_FOURCC('R','V','3','2'):
p_fmt->i_rmask = 0x00ff0000;
p_fmt->i_gmask = 0x0000ff00;
p_fmt->i_bmask = 0x000000ff;
break;
default:
return;
}
}
MaskToShift( &p_fmt->i_lrshift, &p_fmt->i_rrshift,
p_fmt->i_rmask );
MaskToShift( &p_fmt->i_lgshift, &p_fmt->i_rgshift,
p_fmt->i_gmask );
MaskToShift( &p_fmt->i_lbshift, &p_fmt->i_rbshift,
p_fmt->i_bmask );
}
void es_format_Init( es_format_t *fmt,
int i_cat, vlc_fourcc_t i_codec )
{
fmt->i_cat = i_cat;
fmt->i_codec = i_codec;
fmt->i_id = -1;
fmt->i_group = 0;
fmt->i_priority = 0;
fmt->psz_language = NULL;
fmt->psz_description = NULL;
fmt->i_extra_languages = 0;
fmt->p_extra_languages = NULL;
memset( &fmt->audio, 0, sizeof(audio_format_t) );
memset( &fmt->audio_replay_gain, 0, sizeof(audio_replay_gain_t) );
memset( &fmt->video, 0, sizeof(video_format_t) );
memset( &fmt->subs, 0, sizeof(subs_format_t) );
fmt->b_packetized = true;
fmt->i_bitrate = 0;
fmt->i_extra = 0;
fmt->p_extra = NULL;
}
int es_format_Copy( es_format_t *dst, const es_format_t *src )
{
int i;
memcpy( dst, src, sizeof( es_format_t ) );
if( src->psz_language )
dst->psz_language = strdup( src->psz_language );
if( src->psz_description )
dst->psz_description = strdup( src->psz_description );
if( src->i_extra > 0 )
{
dst->i_extra = src->i_extra;
dst->p_extra = malloc( src->i_extra );
memcpy( dst->p_extra, src->p_extra, src->i_extra );
}
else
{
dst->i_extra = 0;
dst->p_extra = NULL;
}
if( src->subs.psz_encoding )
dst->subs.psz_encoding = strdup( src->subs.psz_encoding );
if( src->video.p_palette )
{
dst->video.p_palette =
(video_palette_t*)malloc( sizeof( video_palette_t ) );
memcpy( dst->video.p_palette, src->video.p_palette,
sizeof( video_palette_t ) );
}
dst->i_extra_languages = src->i_extra_languages;
if( dst->i_extra_languages )
dst->p_extra_languages = (extra_languages_t*)
malloc(dst->i_extra_languages * sizeof(*dst->p_extra_languages ));
for( i = 0; i < dst->i_extra_languages; i++ ) {
if( src->p_extra_languages[i].psz_language )
dst->p_extra_languages[i].psz_language = strdup( src->p_extra_languages[i].psz_language );
else
dst->p_extra_languages[i].psz_language = NULL;
if( src->p_extra_languages[i].psz_description )
dst->p_extra_languages[i].psz_description = strdup( src->p_extra_languages[i].psz_description );
else
dst->p_extra_languages[i].psz_description = NULL;
}
return VLC_SUCCESS;
}
void es_format_Clean( es_format_t *fmt )
{
free( fmt->psz_language );
free( fmt->psz_description );
if( fmt->i_extra > 0 ) free( fmt->p_extra );
free( fmt->video.p_palette );
free( fmt->subs.psz_encoding );
if( fmt->i_extra_languages > 0 && fmt->p_extra_languages )
{
int i;
for( i = 0; i < fmt->i_extra_languages; i++ )
{
free( fmt->p_extra_languages[i].psz_language );
free( fmt->p_extra_languages[i].psz_description );
}
free( fmt->p_extra_languages );
}
/* es_format_Clean can be called multiple times */
memset( fmt, 0, sizeof(*fmt) );
}