videoparsers: Add dirac parser

This commit is contained in:
David Schleef 2010-10-09 15:08:39 -07:00
parent fedcf43e29
commit e9ea237d03
6 changed files with 1090 additions and 2 deletions

View file

@ -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

View file

@ -0,0 +1,498 @@
#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_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;
}

View file

@ -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

View file

@ -0,0 +1,352 @@
/* GStreamer
* Copyright (C) 2010 David Schleef <ds@schleef.org>
*
* 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.
*
* <refsect2>
* <title>Example launch line</title>
* |[
* gst-launch -v fakesrc ! gstdiracparse ! FIXME ! fakesink
* ]|
* FIXME Describe what the pipeline does.
* </refsect2>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include <gst/base/gstbytereader.h>
#include <gst/baseparse/gstbaseparse.h>
#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 <ds@schleef.org>");
}
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;
}

View file

@ -0,0 +1,52 @@
/* GStreamer
* Copyright (C) 2010 REAL_NAME <EMAIL_ADDRESS>
*
* 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 <gst/gst.h>
#include <gst/baseparse/gstbaseparse.h>
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

View file

@ -1,5 +1,6 @@
/* GStreamer video parsers
* Copyright (C) 2011 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
* Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
*
* 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;
}