| #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; | |
| } |