mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-25 19:21:06 +00:00
498 lines
13 KiB
C
498 lines
13 KiB
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);
|
|
|
|
|
|
static void schro_video_format_set_std_video_format (DiracSequenceHeader *
|
|
format, int index);
|
|
static void schro_video_format_set_std_frame_rate (DiracSequenceHeader * format,
|
|
int index);
|
|
static void schro_video_format_set_std_aspect_ratio (DiracSequenceHeader *
|
|
format, int index);
|
|
static void schro_video_format_set_std_signal_range (DiracSequenceHeader *
|
|
format, int index);
|
|
static void schro_video_format_set_std_colour_spec (DiracSequenceHeader *
|
|
format, int index);
|
|
|
|
|
|
|
|
|
|
int
|
|
gst_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_uint (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 const 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},
|
|
};
|
|
|
|
static 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 const 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}
|
|
};
|
|
|
|
static 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}
|
|
};
|
|
|
|
static 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}
|
|
};
|
|
|
|
static 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}
|
|
};
|
|
|
|
static 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;
|
|
}
|