Logo Search packages:      
Sourcecode: schroedinger version File versions  Download package

dirac_parse.c

#include "dirac_parse.h"
#include <string.h>

#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))

typedef struct _Unpack Unpack;

struct _Unpack {
  unsigned char *data;
  int n_bits_left;
  int index;
  int guard_bit;
};

static void schro_unpack_init_with_data (Unpack *unpack, unsigned char *data,
    int n_bytes, unsigned int guard_bit);

static unsigned int schro_unpack_decode_bit (Unpack *unpack);
static unsigned int schro_unpack_decode_uint (Unpack *unpack);


void schro_video_format_set_std_video_format (DiracSequenceHeader *format,
    int index);
void schro_video_format_set_std_frame_rate (DiracSequenceHeader *format, int index);
void schro_video_format_set_std_aspect_ratio (DiracSequenceHeader *format, int index);
void schro_video_format_set_std_signal_range (DiracSequenceHeader *format,
    int index);
void schro_video_format_set_std_colour_spec (DiracSequenceHeader *format,
    int index);




int
dirac_sequence_header_parse (DiracSequenceHeader *header,
    unsigned char *data, int n_bytes)
{
  int bit;
  int index;
  Unpack _unpack;
  Unpack *unpack = &_unpack;
  int major_version;
  int minor_version;
  int profile;
  int level;

  memset(header, 0, sizeof(*header));

  schro_unpack_init_with_data (unpack, data, n_bytes, 1);

  /* parse parameters */
  major_version = schro_unpack_decode_uint (unpack);
  minor_version = schro_unpack_decode_uint (unpack);
  profile = schro_unpack_decode_uint (unpack);
  level = schro_unpack_decode_uint (unpack);

  /* base video header */
  index = schro_unpack_decode_uint (unpack);
  schro_video_format_set_std_video_format (header, index);

  header->major_version = major_version;
  header->minor_version = minor_version;
  header->profile = profile;
  header->level = level;

  /* source parameters */
  /* frame dimensions */
  bit = schro_unpack_decode_bit (unpack);
  if (bit) {
    header->width = schro_unpack_decode_uint (unpack);
    header->height = schro_unpack_decode_uint (unpack);
  }

  /* chroma header */
  bit = schro_unpack_decode_bit (unpack);
  if (bit) {
    header->chroma_format = schro_unpack_decode_uint (unpack);
  }

  /* scan header */
  bit = schro_unpack_decode_bit (unpack);
  if (bit) {
    header->interlaced = schro_unpack_decode_bit (unpack);
    if (header->interlaced) {
      header->top_field_first = schro_unpack_decode_bit (unpack);
    }
  }

  /* frame rate */
  bit = schro_unpack_decode_bit (unpack);
  if (bit) {
    index = schro_unpack_decode_uint (unpack);
    if (index == 0) {
      header->frame_rate_numerator = schro_unpack_decode_uint (unpack);
      header->frame_rate_denominator = schro_unpack_decode_uint (unpack);
    } else {
      schro_video_format_set_std_frame_rate (header, index);
    }
  }

  /* aspect ratio */
  bit = schro_unpack_decode_bit (unpack);
  if (bit) {
    index = schro_unpack_decode_uint (unpack);
    if (index == 0) {
      header->aspect_ratio_numerator =
        schro_unpack_decode_uint (unpack);
      header->aspect_ratio_denominator =
        schro_unpack_decode_uint (unpack);
    } else {
      schro_video_format_set_std_aspect_ratio (header, index);
    }
  }

  /* clean area */
  bit = schro_unpack_decode_bit (unpack);
  if (bit) {
    header->clean_width = schro_unpack_decode_uint (unpack);
    header->clean_height = schro_unpack_decode_uint (unpack);
    header->left_offset = schro_unpack_decode_uint (unpack);
    header->top_offset = schro_unpack_decode_uint (unpack);
  }

  /* signal range */
  bit = schro_unpack_decode_bit (unpack);
  if (bit) {
    index = schro_unpack_decode_uint (unpack);
    if (index == 0) {
      header->luma_offset = schro_unpack_decode_uint (unpack);
      header->luma_excursion = schro_unpack_decode_uint (unpack);
      header->chroma_offset = schro_unpack_decode_uint (unpack);
      header->chroma_excursion =
        schro_unpack_decode_uint (unpack);
    } else {
      schro_video_format_set_std_signal_range (header, index);
    }
  }

  /* colour spec */
  bit = schro_unpack_decode_bit (unpack);
  if (bit) {
    index = schro_unpack_decode_uint (unpack);
    schro_video_format_set_std_colour_spec (header, index);
    if (index == 0) {
      /* colour primaries */
      bit = schro_unpack_decode_bit (unpack);
      if (bit) {
        header->colour_primaries = schro_unpack_decode_uint (unpack);
      }
      /* colour matrix */
      bit = schro_unpack_decode_bit (unpack);
      if (bit) {
        header->colour_matrix = schro_unpack_decode_uint (unpack);
      }
      /* transfer function */
      bit = schro_unpack_decode_bit (unpack);
      if (bit) {
        header->transfer_function = schro_unpack_decode_uint (unpack);
      }
    }
  }

  header->interlaced_coding = schro_unpack_decode_uint (unpack);

  return 1;
}

/* standard stuff */

static DiracSequenceHeader
schro_video_formats[] = {
  { 0, 0, 0, 0,
    0, /* custom */
    640, 480, SCHRO_CHROMA_420,
    FALSE, FALSE,
    24000, 1001, 1, 1,
    640, 480, 0, 0,
    0, 255, 128, 255,
    0, 0, 0 },
  { 0, 0, 0, 0,
    1, /* QSIF525 */
    176, 120, SCHRO_CHROMA_420,
    FALSE, FALSE,
    15000, 1001, 10, 11,
    176, 120, 0, 0,
    0, 255, 128, 255,
    1, 1, 0 },
  { 0, 0, 0, 0,
    2, /* QCIF */
    176, 144, SCHRO_CHROMA_420,
    FALSE, TRUE,
    25, 2, 12, 11,
    176, 144, 0, 0,
    0, 255, 128, 255,
    2, 1, 0 },
  { 0, 0, 0, 0,
    3, /* SIF525 */
    352, 240, SCHRO_CHROMA_420,
    FALSE, FALSE,
    15000, 1001, 10, 11,
    352, 240, 0, 0,
    0, 255, 128, 255,
    1, 1, 0 },
  { 0, 0, 0, 0,
    4, /* CIF */
    352, 288, SCHRO_CHROMA_420,
    FALSE, TRUE,
    25, 2, 12, 11,
    352, 288, 0, 0,
    0, 255, 128, 255,
    2, 1, 0 },
  { 0, 0, 0, 0,
    5, /* 4SIF525 */
    704, 480, SCHRO_CHROMA_420,
    FALSE, FALSE,
    15000, 1001, 10, 11,
    704, 480, 0, 0,
    0, 255, 128, 255,
    1, 1, 0 },
  { 0, 0, 0, 0,
    6, /* 4CIF */
    704, 576, SCHRO_CHROMA_420,
    FALSE, TRUE,
    25, 2, 12, 11,
    704, 576, 0, 0,
    0, 255, 128, 255,
    2, 1, 0 },
  { 0, 0, 0, 0,
    7, /* SD480I-60 */
    720, 480, SCHRO_CHROMA_422,
    TRUE, FALSE,
    30000, 1001, 10, 11,
    704, 480, 8, 0,
    64, 876, 512, 896,
    1, 1, 0 },
  { 0, 0, 0, 0,
    8, /* SD576I-50 */
    720, 576, SCHRO_CHROMA_422,
    TRUE, TRUE,
    25, 1, 12, 11,
    704, 576, 8, 0,
    64, 876, 512, 896,
    2, 1, 0 },
  { 0, 0, 0, 0,
    9, /* HD720P-60 */
    1280, 720, SCHRO_CHROMA_422,
    FALSE, TRUE,
    60000, 1001, 1, 1,
    1280, 720, 0, 0,
    64, 876, 512, 896,
    0, 0, 0 },
  { 0, 0, 0, 0,
    10, /* HD720P-50 */
    1280, 720, SCHRO_CHROMA_422,
    FALSE, TRUE,
    50, 1, 1, 1,
    1280, 720, 0, 0,
    64, 876, 512, 896,
    0, 0, 0 },
  { 0, 0, 0, 0,
    11, /* HD1080I-60 */
    1920, 1080, SCHRO_CHROMA_422,
    TRUE, TRUE,
    30000, 1001, 1, 1,
    1920, 1080, 0, 0,
    64, 876, 512, 896,
    0, 0, 0 },
  { 0, 0, 0, 0,
    12, /* HD1080I-50 */
    1920, 1080, SCHRO_CHROMA_422,
    TRUE, TRUE,
    25, 1, 1, 1,
    1920, 1080, 0, 0,
    64, 876, 512, 896,
    0, 0, 0 },
  { 0, 0, 0, 0,
    13, /* HD1080P-60 */
    1920, 1080, SCHRO_CHROMA_422,
    FALSE, TRUE,
    60000, 1001, 1, 1,
    1920, 1080, 0, 0,
    64, 876, 512, 896,
    0, 0, 0 },
  { 0, 0, 0, 0,
    14, /* HD1080P-50 */
    1920, 1080, SCHRO_CHROMA_422,
    FALSE, TRUE,
    50, 1, 1, 1,
    1920, 1080, 0, 0,
    64, 876, 512, 896,
    0, 0, 0 },
  { 0, 0, 0, 0,
    15, /* DC2K */
    2048, 1080, SCHRO_CHROMA_444,
    FALSE, TRUE,
    24, 1, 1, 1,
    2048, 1080, 0, 0,
    256, 3504, 2048, 3584,
    3, 0, 0 },
  { 0, 0, 0, 0,
    16, /* DC4K */
    4096, 2160, SCHRO_CHROMA_444,
    FALSE, TRUE,
    24, 1, 1, 1,
    2048, 1536, 0, 0,
    256, 3504, 2048, 3584,
    3, 0, 0 },
};

void
schro_video_format_set_std_video_format (DiracSequenceHeader *format,
    int index)
{

  if (index < 0 || index >= ARRAY_SIZE(schro_video_formats)) {
    return;
  }

  memcpy (format, schro_video_formats + index, sizeof(DiracSequenceHeader));
}

typedef struct _SchroFrameRate SchroFrameRate;
struct _SchroFrameRate {
  int numerator;
  int denominator;
};

static SchroFrameRate
schro_frame_rates[] = {
  { 0, 0 },
  { 24000, 1001 },
  { 24, 1 },
  { 25, 1 },
  { 30000, 1001 },
  { 30, 1 },
  { 50, 1 },
  { 60000, 1001 },
  { 60, 1 },
  { 15000, 1001 },
  { 25, 2 }
};

void schro_video_format_set_std_frame_rate (DiracSequenceHeader *format, int index)
{
  if (index < 1 || index >= ARRAY_SIZE(schro_frame_rates)) {
    return;
  }

  format->frame_rate_numerator = schro_frame_rates[index].numerator;
  format->frame_rate_denominator = schro_frame_rates[index].denominator;
}

typedef struct _SchroPixelAspectRatio SchroPixelAspectRatio;
struct _SchroPixelAspectRatio {
  int numerator;
  int denominator;
};

static const SchroPixelAspectRatio
schro_aspect_ratios[] = {
  { 0, 0 },
  { 1, 1 },
  { 10, 11 },
  { 12, 11 },
  { 40, 33 },
  { 16, 11 },
  { 4, 3 }
};

void schro_video_format_set_std_aspect_ratio (DiracSequenceHeader *format, int index)
{
  if (index < 1 || index >= ARRAY_SIZE(schro_aspect_ratios)) {
    return;
  }

  format->aspect_ratio_numerator = schro_aspect_ratios[index].numerator;
  format->aspect_ratio_denominator = schro_aspect_ratios[index].denominator;

}

typedef struct _SchroSignalRangeStruct SchroSignalRangeStruct;
struct _SchroSignalRangeStruct {
  int luma_offset;
  int luma_excursion;
  int chroma_offset;
  int chroma_excursion;
};

static const SchroSignalRangeStruct schro_signal_ranges[] = {
  { 0, 0, 0, 0 },
  { 0, 255, 128, 255 },
  { 16, 219, 128, 224 },
  { 64, 876, 512, 896 },
  { 256, 3504, 2048, 3584 }
};

void schro_video_format_set_std_signal_range (DiracSequenceHeader *format,
    int i)
{
  if (i < 1 || i >= ARRAY_SIZE(schro_signal_ranges)) {
    return;
  }

  format->luma_offset = schro_signal_ranges[i].luma_offset;
  format->luma_excursion = schro_signal_ranges[i].luma_excursion;
  format->chroma_offset = schro_signal_ranges[i].chroma_offset;
  format->chroma_excursion = schro_signal_ranges[i].chroma_excursion;
}

typedef struct _SchroColourSpecStruct SchroColourSpecStruct;
struct _SchroColourSpecStruct {
  int colour_primaries;
  int colour_matrix;
  int transfer_function;
};

static const SchroColourSpecStruct schro_colour_specs[] = {
  { /* Custom */
    SCHRO_COLOUR_PRIMARY_HDTV,
    SCHRO_COLOUR_MATRIX_HDTV,
    SCHRO_TRANSFER_CHAR_TV_GAMMA
  },
  { /* SDTV 525 */
    SCHRO_COLOUR_PRIMARY_SDTV_525,
    SCHRO_COLOUR_MATRIX_SDTV,
    SCHRO_TRANSFER_CHAR_TV_GAMMA
  },
  { /* SDTV 625 */
    SCHRO_COLOUR_PRIMARY_SDTV_625,
    SCHRO_COLOUR_MATRIX_SDTV,
    SCHRO_TRANSFER_CHAR_TV_GAMMA
  },
  { /* HDTV */
    SCHRO_COLOUR_PRIMARY_HDTV,
    SCHRO_COLOUR_MATRIX_HDTV,
    SCHRO_TRANSFER_CHAR_TV_GAMMA
  },
  { /* Cinema */
    SCHRO_COLOUR_PRIMARY_CINEMA,
    SCHRO_COLOUR_MATRIX_HDTV,
    SCHRO_TRANSFER_CHAR_TV_GAMMA
  }
};

void schro_video_format_set_std_colour_spec (DiracSequenceHeader *format,
    int i)
{
  if (i < 0 || i >= ARRAY_SIZE(schro_colour_specs)) {
    return;
  }

  format->colour_primaries = schro_colour_specs[i].colour_primaries;
  format->colour_matrix = schro_colour_specs[i].colour_matrix;
  format->transfer_function = schro_colour_specs[i].transfer_function;
}


/* unpack */

static void
schro_unpack_init_with_data (Unpack *unpack, unsigned char *data,
    int n_bytes, unsigned int guard_bit)
{
  memset (unpack, 0, sizeof(Unpack));

  unpack->data = data;
  unpack->n_bits_left = 8*n_bytes;
  unpack->guard_bit = guard_bit;
}

static unsigned int
schro_unpack_decode_bit (Unpack *unpack)
{
  int bit;

  if (unpack->n_bits_left < 1) {
    return unpack->guard_bit;
  }
  bit = (unpack->data[unpack->index>>3]>>(7 - (unpack->index & 7))) & 1;
  unpack->index++;
  unpack->n_bits_left--;

  return bit;
}

static unsigned int
schro_unpack_decode_uint (Unpack *unpack)
{
  int count;
  int value; 
  
  count = 0;
  value = 0;
  while(!schro_unpack_decode_bit (unpack)) {
    count++;
    value <<= 1;
    value |= schro_unpack_decode_bit (unpack);
  }

  return (1<<count) - 1 + value;
}


Generated by  Doxygen 1.6.0   Back to index