|
Packit |
a38265 |
/*
|
|
Packit |
a38265 |
dirac.c
|
|
Packit |
a38265 |
*/
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
#include "config.h"
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
#ifdef HAVE_STDINT_H
|
|
Packit |
a38265 |
#include <stdint.h>
|
|
Packit |
a38265 |
#endif
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
#include "dirac.h"
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
typedef struct
|
|
Packit |
a38265 |
dirac_bs_s
|
|
Packit |
a38265 |
{
|
|
Packit |
a38265 |
uint8_t *p_start;
|
|
Packit |
a38265 |
uint8_t *p;
|
|
Packit |
a38265 |
uint8_t *p_end;
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
int i_left; /* i_count number of available bits */
|
|
Packit |
a38265 |
} dirac_bs_t;
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
static inline void
|
|
Packit |
a38265 |
dirac_bs_init( dirac_bs_t *s, void *p_data, int i_data )
|
|
Packit |
a38265 |
{
|
|
Packit |
a38265 |
s->p_start = p_data;
|
|
Packit |
a38265 |
s->p = p_data;
|
|
Packit |
a38265 |
s->p_end = s->p + i_data;
|
|
Packit |
a38265 |
s->i_left = 8;
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
static inline ogg_uint32_t
|
|
Packit |
a38265 |
dirac_bs_read( dirac_bs_t *s, int i_count )
|
|
Packit |
a38265 |
{
|
|
Packit |
a38265 |
static ogg_uint32_t i_mask[33] =
|
|
Packit |
a38265 |
{ 0x00,
|
|
Packit |
a38265 |
0x01, 0x03, 0x07, 0x0f,
|
|
Packit |
a38265 |
0x1f, 0x3f, 0x7f, 0xff,
|
|
Packit |
a38265 |
0x1ff, 0x3ff, 0x7ff, 0xfff,
|
|
Packit |
a38265 |
0x1fff, 0x3fff, 0x7fff, 0xffff,
|
|
Packit |
a38265 |
0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
|
|
Packit |
a38265 |
0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
|
|
Packit |
a38265 |
0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
|
|
Packit |
a38265 |
0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
|
|
Packit |
a38265 |
int i_shr;
|
|
Packit |
a38265 |
ogg_uint32_t i_result = 0;
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
while( i_count > 0 )
|
|
Packit |
a38265 |
{
|
|
Packit |
a38265 |
if( s->p >= s->p_end )
|
|
Packit |
a38265 |
{
|
|
Packit |
a38265 |
break;
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
if( ( i_shr = s->i_left - i_count ) >= 0 )
|
|
Packit |
a38265 |
{
|
|
Packit |
a38265 |
/* more in the buffer than requested */
|
|
Packit |
a38265 |
i_result |= ( *s->p >> i_shr )&i_mask[i_count];
|
|
Packit |
a38265 |
s->i_left -= i_count;
|
|
Packit |
a38265 |
if( s->i_left == 0 )
|
|
Packit |
a38265 |
{
|
|
Packit |
a38265 |
s->p++;
|
|
Packit |
a38265 |
s->i_left = 8;
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
return( i_result );
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
else
|
|
Packit |
a38265 |
{
|
|
Packit |
a38265 |
/* less in the buffer than requested */
|
|
Packit |
a38265 |
i_result |= (*s->p&i_mask[s->i_left]) << -i_shr;
|
|
Packit |
a38265 |
i_count -= s->i_left;
|
|
Packit |
a38265 |
s->p++;
|
|
Packit |
a38265 |
s->i_left = 8;
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
return( i_result );
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
static inline void
|
|
Packit |
a38265 |
dirac_bs_skip( dirac_bs_t *s, int i_count )
|
|
Packit |
a38265 |
{
|
|
Packit |
a38265 |
s->i_left -= i_count;
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
while( s->i_left <= 0 )
|
|
Packit |
a38265 |
{
|
|
Packit |
a38265 |
s->p++;
|
|
Packit |
a38265 |
s->i_left += 8;
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
static ogg_uint32_t
|
|
Packit |
a38265 |
dirac_uint ( dirac_bs_t *p_bs )
|
|
Packit |
a38265 |
{
|
|
Packit |
a38265 |
ogg_uint32_t count = 0, value = 0;
|
|
Packit |
a38265 |
while( !dirac_bs_read ( p_bs, 1 ) ) {
|
|
Packit |
a38265 |
count++;
|
|
Packit |
a38265 |
value <<= 1;
|
|
Packit |
a38265 |
value |= dirac_bs_read ( p_bs, 1 );
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
return (1<
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
static int
|
|
Packit |
a38265 |
dirac_bool ( dirac_bs_t *p_bs )
|
|
Packit |
a38265 |
{
|
|
Packit |
a38265 |
return dirac_bs_read ( p_bs, 1 );
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
int
|
|
Packit |
a38265 |
dirac_parse_info (dirac_info *info, unsigned char * data, long len)
|
|
Packit |
a38265 |
{
|
|
Packit |
a38265 |
dirac_bs_t bs;
|
|
Packit |
a38265 |
ogg_uint32_t video_format;
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
static const struct {
|
|
Packit |
a38265 |
ogg_uint32_t fps_numerator, fps_denominator;
|
|
Packit |
a38265 |
} dirac_frate_tbl[] = { /* table 10.3 */
|
|
Packit |
a38265 |
{1,1}, /* this first value is never used */
|
|
Packit |
a38265 |
{24000,1001}, {24,1}, {25,1}, {30000,1001}, {30,1},
|
|
Packit |
a38265 |
{50,1}, {60000,1001}, {60,1}, {15000,1001}, {25,2}
|
|
Packit |
a38265 |
};
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
static const ogg_uint32_t dirac_vidfmt_frate[] = { /* table C.1 */
|
|
Packit |
a38265 |
1, 9, 10, 9, 10, 9, 10, 4, 3, 7, 6, 4, 3, 7, 6, 2, 2, 7, 6, 7, 6
|
|
Packit |
a38265 |
};
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
static const int dirac_source_sampling[] = { /* extracted from table C.1 */
|
|
Packit |
a38265 |
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
|
|
Packit |
a38265 |
};
|
|
Packit |
a38265 |
static const int dirac_top_field_first[] = { /* from table C.1 */
|
|
Packit |
a38265 |
0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
|
Packit |
a38265 |
};
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
static const struct {
|
|
Packit |
a38265 |
ogg_uint32_t width, height;
|
|
Packit |
a38265 |
} dirac_fsize_tbl[] = { /* table 10.3 framesize */
|
|
Packit |
a38265 |
{640,460}, {24,1}, {176,120}, {352,240}, {352,288},
|
|
Packit |
a38265 |
{704,480}, {704,576}, {720,480}, {720,576},
|
|
Packit |
a38265 |
{1280, 720}, {1280, 720}, {1920, 1080}, {1920, 1080},
|
|
Packit |
a38265 |
{1920, 1080}, {1920, 1080}, {2048, 1080}, {4096, 2160}
|
|
Packit |
a38265 |
};
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
/* read in useful bits from sequence header */
|
|
Packit |
a38265 |
dirac_bs_init( &bs, data, len);
|
|
Packit |
a38265 |
dirac_bs_skip( &bs, 13*8); /* parse_info_header */
|
|
Packit |
a38265 |
info->major_version = dirac_uint( &bs ); /* major_version */
|
|
Packit |
a38265 |
info->minor_version = dirac_uint( &bs ); /* minor_version */
|
|
Packit |
a38265 |
info->profile = dirac_uint( &bs ); /* profile */
|
|
Packit |
a38265 |
info->level = dirac_uint( &bs ); /* level */
|
|
Packit |
a38265 |
info->video_format = video_format = dirac_uint( &bs ); /* index */
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
if (video_format >= (sizeof(dirac_fsize_tbl) / sizeof(dirac_fsize_tbl[0]))) {
|
|
Packit |
a38265 |
return -1;
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
info->width = dirac_fsize_tbl[video_format].width;
|
|
Packit |
a38265 |
info->height = dirac_fsize_tbl[video_format].height;
|
|
Packit |
a38265 |
if (dirac_bool( &bs )) {
|
|
Packit |
a38265 |
info->width = dirac_uint( &bs ); /* frame_width */
|
|
Packit |
a38265 |
info->height = dirac_uint( &bs ); /* frame_height */
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
if (dirac_bool( &bs )) {
|
|
Packit |
a38265 |
info->chroma_format = dirac_uint( &bs ); /* chroma_format */
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
if (dirac_bool( &bs )) { /* custom_scan_format_flag */
|
|
Packit |
a38265 |
int scan_format = dirac_uint( &bs ); /* scan_format */
|
|
Packit |
a38265 |
if (scan_format < 2) {
|
|
Packit |
a38265 |
info->interlaced = scan_format;
|
|
Packit |
a38265 |
} else { /* other scan_format values are reserved */
|
|
Packit |
a38265 |
info->interlaced = 0;
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
} else { /* no custom scan_format, use the preset value */
|
|
Packit |
a38265 |
info->interlaced = dirac_source_sampling[video_format];
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
/* field order is set by video_format and cannot be custom */
|
|
Packit |
a38265 |
info->top_field_first = dirac_top_field_first[video_format];
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
info->fps_numerator = dirac_frate_tbl[dirac_vidfmt_frate[video_format]].fps_numerator;
|
|
Packit |
a38265 |
info->fps_denominator = dirac_frate_tbl[dirac_vidfmt_frate[video_format]].fps_denominator;
|
|
Packit |
a38265 |
if (dirac_bool( &bs )) {
|
|
Packit |
a38265 |
ogg_uint32_t frame_rate_index = dirac_uint( &bs );
|
|
Packit |
a38265 |
info->fps_numerator = dirac_frate_tbl[frame_rate_index].fps_numerator;
|
|
Packit |
a38265 |
info->fps_denominator = dirac_frate_tbl[frame_rate_index].fps_denominator;
|
|
Packit |
a38265 |
if (frame_rate_index == 0) {
|
|
Packit |
a38265 |
info->fps_numerator = dirac_uint( &bs );
|
|
Packit |
a38265 |
info->fps_denominator = dirac_uint( &bs );
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
}
|
|
Packit |
a38265 |
|
|
Packit |
a38265 |
return 0;
|
|
Packit |
a38265 |
}
|