mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-30 12:10:37 +00:00
72edd1467b
Adds code that parses headers of various formats encapsulated in Ogg in order to calculate timestamps and durations of each buffer. Removes the creation of helper decoder elements to do this calculation via conversion queries. Fixes: #344013, #568014.
501 lines
13 KiB
C
501 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);
|
|
|
|
|
|
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;
|
|
}
|