diff --git a/gst/videoparsers/Makefile.am b/gst/videoparsers/Makefile.am index 59b5160211..a344117a71 100644 --- a/gst/videoparsers/Makefile.am +++ b/gst/videoparsers/Makefile.am @@ -1,11 +1,15 @@ plugin_LTLIBRARIES = libgsth263parse.la libgsth263parse_la_SOURCES = plugin.c \ - h263parse.c gsth263parse.c gsth264parse.c h264parse.c + h263parse.c gsth263parse.c \ + gsth264parse.c h264parse.c \ + gstdiracparse.c dirac_parse.c libgsth263parse_la_CFLAGS = $(GST_CFLAGS) libgsth263parse_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) libgsth263parse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgsth263parse_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = gsth263parse.h h263parse.h \ - gsth264parse.h h264parse.h + gsth264parse.h h264parse.h \ + gstdiracparse.h dirac_parse.h + diff --git a/gst/videoparsers/dirac_parse.c b/gst/videoparsers/dirac_parse.c new file mode 100644 index 0000000000..3a3193d925 --- /dev/null +++ b/gst/videoparsers/dirac_parse.c @@ -0,0 +1,498 @@ + +#include "dirac_parse.h" +#include + +#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_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 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; +} diff --git a/gst/videoparsers/dirac_parse.h b/gst/videoparsers/dirac_parse.h new file mode 100644 index 0000000000..9dc4ffec5f --- /dev/null +++ b/gst/videoparsers/dirac_parse.h @@ -0,0 +1,178 @@ + +#ifndef __DIRAC_PARSE_H__ +#define __DIRAC_PARSE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +typedef enum _SchroParseCode { + SCHRO_PARSE_CODE_SEQUENCE_HEADER = 0x00, + SCHRO_PARSE_CODE_END_OF_SEQUENCE = 0x10, + SCHRO_PARSE_CODE_AUXILIARY_DATA = 0x20, + SCHRO_PARSE_CODE_PADDING = 0x30, + + SCHRO_PARSE_CODE_INTRA_REF = 0x0c, + SCHRO_PARSE_CODE_INTRA_NON_REF = 0x08, + SCHRO_PARSE_CODE_INTRA_REF_NOARITH = 0x4c, + SCHRO_PARSE_CODE_INTRA_NON_REF_NOARITH = 0x48, + + SCHRO_PARSE_CODE_INTER_REF_1 = 0x0d, + SCHRO_PARSE_CODE_INTER_REF_1_NOARITH = 0x4d, + SCHRO_PARSE_CODE_INTER_REF_2 = 0x0e, + SCHRO_PARSE_CODE_INTER_REF_2_NOARITH = 0x4e, + + SCHRO_PARSE_CODE_INTER_NON_REF_1 = 0x09, + SCHRO_PARSE_CODE_INTER_NON_REF_1_NOARITH = 0x49, + SCHRO_PARSE_CODE_INTER_NON_REF_2 = 0x0a, + SCHRO_PARSE_CODE_INTER_NON_REF_2_NOARITH = 0x4a, + + SCHRO_PARSE_CODE_LD_INTRA_REF = 0xcc, + SCHRO_PARSE_CODE_LD_INTRA_NON_REF = 0xc8 +} SchroParseCode; + +#define SCHRO_PARSE_CODE_PICTURE(is_ref,n_refs,is_lowdelay,is_noarith) \ + (8 | ((is_ref)<<2) | (n_refs) | ((is_lowdelay)<<7) | ((is_noarith)<<6)) + +#define SCHRO_PARSE_CODE_IS_SEQ_HEADER(x) ((x) == SCHRO_PARSE_CODE_SEQUENCE_HEADER) +#define SCHRO_PARSE_CODE_IS_END_OF_SEQUENCE(x) ((x) == SCHRO_PARSE_CODE_END_OF_SEQUENCE) +#define SCHRO_PARSE_CODE_IS_AUXILIARY_DATA(x) ((x) == SCHRO_PARSE_CODE_AUXILIARY_DATA) +#define SCHRO_PARSE_CODE_IS_PADDING(x) ((x) == SCHRO_PARSE_CODE_PADDING) +#define SCHRO_PARSE_CODE_IS_PICTURE(x) ((x) & 0x8) +#define SCHRO_PARSE_CODE_IS_LOW_DELAY(x) (((x) & 0x88) == 0x88) +#define SCHRO_PARSE_CODE_IS_CORE_SYNTAX(x) (((x) & 0x88) == 0x08) +#define SCHRO_PARSE_CODE_USING_AC(x) (((x) & 0x48) == 0x08) +#define SCHRO_PARSE_CODE_IS_REFERENCE(x) (((x) & 0xc) == 0x0c) +#define SCHRO_PARSE_CODE_IS_NON_REFERENCE(x) (((x) & 0xc) == 0x08) +#define SCHRO_PARSE_CODE_NUM_REFS(x) ((x) & 0x3) +#define SCHRO_PARSE_CODE_IS_INTRA(x) (SCHRO_PARSE_CODE_IS_PICTURE(x) && SCHRO_PARSE_CODE_NUM_REFS(x) == 0) +#define SCHRO_PARSE_CODE_IS_INTER(x) (SCHRO_PARSE_CODE_IS_PICTURE(x) && SCHRO_PARSE_CODE_NUM_REFS(x) > 0) + +#define SCHRO_PARSE_HEADER_SIZE (4+1+4+4) + +typedef enum _SchroVideoFormatEnum { + SCHRO_VIDEO_FORMAT_CUSTOM = 0, + SCHRO_VIDEO_FORMAT_QSIF, + SCHRO_VIDEO_FORMAT_QCIF, + SCHRO_VIDEO_FORMAT_SIF, + SCHRO_VIDEO_FORMAT_CIF, + SCHRO_VIDEO_FORMAT_4SIF, + SCHRO_VIDEO_FORMAT_4CIF, + SCHRO_VIDEO_FORMAT_SD480I_60, + SCHRO_VIDEO_FORMAT_SD576I_50, + SCHRO_VIDEO_FORMAT_HD720P_60, + SCHRO_VIDEO_FORMAT_HD720P_50, + SCHRO_VIDEO_FORMAT_HD1080I_60, + SCHRO_VIDEO_FORMAT_HD1080I_50, + SCHRO_VIDEO_FORMAT_HD1080P_60, + SCHRO_VIDEO_FORMAT_HD1080P_50, + SCHRO_VIDEO_FORMAT_DC2K_24, + SCHRO_VIDEO_FORMAT_DC4K_24 +} SchroVideoFormatEnum; + +typedef enum _SchroChromaFormat { + SCHRO_CHROMA_444 = 0, + SCHRO_CHROMA_422, + SCHRO_CHROMA_420 +} SchroChromaFormat; + +#define SCHRO_CHROMA_FORMAT_H_SHIFT(format) (((format) == SCHRO_CHROMA_444)?0:1) +#define SCHRO_CHROMA_FORMAT_V_SHIFT(format) (((format) == SCHRO_CHROMA_420)?1:0) + +typedef enum _SchroSignalRange { + SCHRO_SIGNAL_RANGE_CUSTOM = 0, + SCHRO_SIGNAL_RANGE_8BIT_FULL = 1, + SCHRO_SIGNAL_RANGE_8BIT_VIDEO = 2, + SCHRO_SIGNAL_RANGE_10BIT_VIDEO = 3, + SCHRO_SIGNAL_RANGE_12BIT_VIDEO = 4 +} SchroSignalRange; + +typedef enum _SchroColourSpec { + SCHRO_COLOUR_SPEC_CUSTOM = 0, + SCHRO_COLOUR_SPEC_SDTV_525 = 1, + SCHRO_COLOUR_SPEC_SDTV_625 = 2, + SCHRO_COLOUR_SPEC_HDTV = 3, + SCHRO_COLOUR_SPEC_CINEMA = 4 +} SchroColourSpec; + +typedef enum _SchroColourPrimaries { + SCHRO_COLOUR_PRIMARY_HDTV = 0, + SCHRO_COLOUR_PRIMARY_SDTV_525 = 1, + SCHRO_COLOUR_PRIMARY_SDTV_625 = 2, + SCHRO_COLOUR_PRIMARY_CINEMA = 3 +} SchroColourPrimaries; + +typedef enum _SchroColourMatrix { + SCHRO_COLOUR_MATRIX_HDTV = 0, + SCHRO_COLOUR_MATRIX_SDTV = 1, + SCHRO_COLOUR_MATRIX_REVERSIBLE = 2 +}SchroColourMatrix; + +typedef enum _SchroTransferFunction { + SCHRO_TRANSFER_CHAR_TV_GAMMA = 0, + SCHRO_TRANSFER_CHAR_EXTENDED_GAMUT = 1, + SCHRO_TRANSFER_CHAR_LINEAR = 2, + SCHRO_TRANSFER_CHAR_DCI_GAMMA = 3 +} SchroTransferFunction; + + + +typedef struct _DiracSequenceHeader DiracSequenceHeader; + +struct _DiracSequenceHeader { + int major_version; + int minor_version; + int profile; + int level; + + int index; + int width; + int height; + int chroma_format; + + int interlaced; + int top_field_first; + + int frame_rate_numerator; + int frame_rate_denominator; + int aspect_ratio_numerator; + int aspect_ratio_denominator; + + int clean_width; + int clean_height; + int left_offset; + int top_offset; + + int luma_offset; + int luma_excursion; + int chroma_offset; + int chroma_excursion; + + int colour_primaries; + int colour_matrix; + int transfer_function; + + int interlaced_coding; + + int unused0; + int unused1; + int unused2; +}; + + +int dirac_sequence_header_parse (DiracSequenceHeader *header, + unsigned char *data, int length); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/gst/videoparsers/gstdiracparse.c b/gst/videoparsers/gstdiracparse.c new file mode 100644 index 0000000000..4ddcd3a5ae --- /dev/null +++ b/gst/videoparsers/gstdiracparse.c @@ -0,0 +1,352 @@ +/* GStreamer + * Copyright (C) 2010 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/** + * SECTION:element-gstdiracparse + * + * The gstdiracparse element does FIXME stuff. + * + * + * Example launch line + * |[ + * gst-launch -v fakesrc ! gstdiracparse ! FIXME ! fakesink + * ]| + * FIXME Describe what the pipeline does. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include "gstdiracparse.h" + +/* prototypes */ + + +static void gst_dirac_parse_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec); +static void gst_dirac_parse_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec); +static void gst_dirac_parse_dispose (GObject * object); +static void gst_dirac_parse_finalize (GObject * object); + +static gboolean gst_dirac_parse_start (GstBaseParse * parse); +static gboolean gst_dirac_parse_stop (GstBaseParse * parse); +static gboolean gst_dirac_parse_set_sink_caps (GstBaseParse * parse, + GstCaps * caps); +static gboolean gst_dirac_parse_check_valid_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, guint * framesize, gint * skipsize); +static GstFlowReturn gst_dirac_parse_parse_frame (GstBaseParse * parse, + GstBaseParseFrame * frame); +static gboolean gst_dirac_parse_convert (GstBaseParse * parse, + GstFormat src_format, gint64 src_value, GstFormat dest_format, + gint64 * dest_value); +static gboolean gst_dirac_parse_event (GstBaseParse * parse, GstEvent * event); +static gboolean gst_dirac_parse_src_event (GstBaseParse * parse, + GstEvent * event); +static GstFlowReturn gst_dirac_parse_pre_push_frame (GstBaseParse * parse, + GstBaseParseFrame * frame); + +enum +{ + PROP_0 +}; + +/* pad templates */ + +static GstStaticPadTemplate gst_dirac_parse_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/unknown") + ); + +static GstStaticPadTemplate gst_dirac_parse_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/unknown") + ); + +/* class initialization */ + +GST_BOILERPLATE (GstDiracParse, gst_dirac_parse, GstBaseParse, + GST_TYPE_BASE_PARSE); + +static void +gst_dirac_parse_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_dirac_parse_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_dirac_parse_sink_template)); + + gst_element_class_set_details_simple (element_class, "FIXME", + "Generic", "FIXME", "David Schleef "); +} + +static void +gst_dirac_parse_class_init (GstDiracParseClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstBaseParseClass *base_parse_class = GST_BASE_PARSE_CLASS (klass); + + gobject_class->set_property = gst_dirac_parse_set_property; + gobject_class->get_property = gst_dirac_parse_get_property; + gobject_class->dispose = gst_dirac_parse_dispose; + gobject_class->finalize = gst_dirac_parse_finalize; + base_parse_class->start = GST_DEBUG_FUNCPTR (gst_dirac_parse_start); + base_parse_class->stop = GST_DEBUG_FUNCPTR (gst_dirac_parse_stop); + base_parse_class->set_sink_caps = + GST_DEBUG_FUNCPTR (gst_dirac_parse_set_sink_caps); + base_parse_class->check_valid_frame = + GST_DEBUG_FUNCPTR (gst_dirac_parse_check_valid_frame); + base_parse_class->parse_frame = + GST_DEBUG_FUNCPTR (gst_dirac_parse_parse_frame); + base_parse_class->convert = GST_DEBUG_FUNCPTR (gst_dirac_parse_convert); + base_parse_class->event = GST_DEBUG_FUNCPTR (gst_dirac_parse_event); + base_parse_class->src_event = GST_DEBUG_FUNCPTR (gst_dirac_parse_src_event); + base_parse_class->pre_push_frame = + GST_DEBUG_FUNCPTR (gst_dirac_parse_pre_push_frame); + +} + +static void +gst_dirac_parse_init (GstDiracParse * diracparse, + GstDiracParseClass * diracparse_class) +{ + gst_base_parse_set_min_frame_size (GST_BASE_PARSE (diracparse), 13); + +} + +void +gst_dirac_parse_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + GstDiracParse *diracparse; + + g_return_if_fail (GST_IS_DIRAC_PARSE (object)); + diracparse = GST_DIRAC_PARSE (object); + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_dirac_parse_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GstDiracParse *diracparse; + + g_return_if_fail (GST_IS_DIRAC_PARSE (object)); + diracparse = GST_DIRAC_PARSE (object); + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_dirac_parse_dispose (GObject * object) +{ + GstDiracParse *diracparse; + + g_return_if_fail (GST_IS_DIRAC_PARSE (object)); + diracparse = GST_DIRAC_PARSE (object); + + /* clean up as possible. may be called multiple times */ + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +void +gst_dirac_parse_finalize (GObject * object) +{ + GstDiracParse *diracparse; + + g_return_if_fail (GST_IS_DIRAC_PARSE (object)); + diracparse = GST_DIRAC_PARSE (object); + + /* clean up object here */ + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + + +static gboolean +gst_dirac_parse_start (GstBaseParse * parse) +{ + return TRUE; +} + +static gboolean +gst_dirac_parse_stop (GstBaseParse * parse) +{ + return TRUE; +} + +static gboolean +gst_dirac_parse_set_sink_caps (GstBaseParse * parse, GstCaps * caps) +{ + /* Called when sink caps are set */ + return TRUE; +} + +static gboolean +gst_dirac_parse_frame_header (GstDiracParse * diracparse, + GstBuffer * buffer, guint * framesize) +{ + int next_header; + + next_header = GST_READ_UINT32_BE (GST_BUFFER_DATA (buffer) + 5); + + *framesize = next_header; + return TRUE; +} + +static gboolean +gst_dirac_parse_check_valid_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) +{ + GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (frame->buffer); + GstDiracParse *diracparse = GST_DIRAC_PARSE (parse); + int off; + guint32 next_header; + gboolean sync; + gboolean drain; + + if (G_UNLIKELY (GST_BUFFER_SIZE (frame->buffer) < 13)) + return FALSE; + + off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff, + 0x42424344, 0, GST_BUFFER_SIZE (frame->buffer)); + + if (off < 0) { + *skipsize = GST_BUFFER_SIZE (frame->buffer) - 3; + return FALSE; + } + + GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off); + + if (off > 0) { + GST_ERROR ("skipping %d", off); + *skipsize = off; + return FALSE; + } + + if (!gst_dirac_parse_frame_header (diracparse, frame->buffer, framesize)) { + GST_ERROR ("bad header"); + *skipsize = 3; + return FALSE; + } + + GST_LOG ("framesize %d", *framesize); + + sync = GST_BASE_PARSE_FRAME_SYNC (frame); + drain = GST_BASE_PARSE_FRAME_DRAIN (frame); + + if (!sync && !drain) { + guint32 next_sync_word; + + next_header = GST_READ_UINT32_BE (GST_BUFFER_DATA (frame->buffer) + 5); + GST_LOG ("next header %d", next_header); + + if (!gst_byte_reader_skip (&reader, next_header) || + !gst_byte_reader_get_uint32_be (&reader, &next_sync_word)) { + gst_base_parse_set_min_frame_size (parse, next_header + 4); + *skipsize = 0; + return FALSE; + } else { + if (next_sync_word != 0x42424344) { + *skipsize = 3; + return FALSE; + } else { + gst_base_parse_set_min_frame_size (parse, next_header); + + } + } + } + + return TRUE; +} + +static GstFlowReturn +gst_dirac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + //GstDiracParse * diracparse = GST_DIRAC_PARSE (parse); + + /* Called when processing incoming buffers. Function should parse + a checked frame. */ + /* MUST implement */ + + if (GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (parse)) == NULL) { + GstCaps *caps = gst_caps_new_simple ("video/x-dirac", NULL); + + gst_buffer_set_caps (frame->buffer, caps); + gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps); + gst_caps_unref (caps); + + } + + gst_base_parse_set_min_frame_size (parse, 13); + + return GST_FLOW_OK; +} + +static gboolean +gst_dirac_parse_convert (GstBaseParse * parse, GstFormat src_format, + gint64 src_value, GstFormat dest_format, gint64 * dest_value) +{ + /* Convert between formats */ + + return FALSE; +} + +static gboolean +gst_dirac_parse_event (GstBaseParse * parse, GstEvent * event) +{ + /* Sink pad event handler */ + + return FALSE; +} + +static gboolean +gst_dirac_parse_src_event (GstBaseParse * parse, GstEvent * event) +{ + /* Src pad event handler */ + + return FALSE; +} + +static GstFlowReturn +gst_dirac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + + return GST_FLOW_OK; +} diff --git a/gst/videoparsers/gstdiracparse.h b/gst/videoparsers/gstdiracparse.h new file mode 100644 index 0000000000..64a1b8123d --- /dev/null +++ b/gst/videoparsers/gstdiracparse.h @@ -0,0 +1,52 @@ +/* GStreamer + * Copyright (C) 2010 REAL_NAME + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GST_DIRAC_PARSE_H_ +#define _GST_DIRAC_PARSE_H_ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_DIRAC_PARSE (gst_dirac_parse_get_type()) +#define GST_DIRAC_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DIRAC_PARSE,GstDiracParse)) +#define GST_DIRAC_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DIRAC_PARSE,GstDiracParseClass)) +#define GST_IS_DIRAC_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DIRAC_PARSE)) +#define GST_IS_DIRAC_PARSE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DIRAC_PARSE)) + +typedef struct _GstDiracParse GstDiracParse; +typedef struct _GstDiracParseClass GstDiracParseClass; + +struct _GstDiracParse +{ + GstBaseParse base_diracparse; + +}; + +struct _GstDiracParseClass +{ + GstBaseParseClass base_diracparse_class; +}; + +GType gst_dirac_parse_get_type (void); + +G_END_DECLS + +#endif diff --git a/gst/videoparsers/plugin.c b/gst/videoparsers/plugin.c index 463e417cb6..cfd8a48285 100644 --- a/gst/videoparsers/plugin.c +++ b/gst/videoparsers/plugin.c @@ -1,5 +1,6 @@ /* GStreamer video parsers * Copyright (C) 2011 Mark Nauwelaerts + * Copyright (C) 2009 Tim-Philipp Müller * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,6 +24,7 @@ #include "gsth263parse.h" #include "gsth264parse.h" +#include "gstdiracparse.h" static gboolean plugin_init (GstPlugin * plugin) @@ -33,6 +35,8 @@ plugin_init (GstPlugin * plugin) GST_RANK_NONE, GST_TYPE_H263_PARSE); ret = gst_element_register (plugin, "h264parse", GST_RANK_NONE, GST_TYPE_H264_PARSE); + ret = gst_element_register (plugin, "diracparse", + GST_RANK_NONE, GST_TYPE_DIRAC_PARSE); return ret; }