diff --git a/gst/videoparsers/gstdiracparse.c b/gst/videoparsers/gstdiracparse.c index fbd157abb5..3feaa41926 100644 --- a/gst/videoparsers/gstdiracparse.c +++ b/gst/videoparsers/gstdiracparse.c @@ -36,7 +36,9 @@ #include #include +#include #include "gstdiracparse.h" +#include "dirac_parse.h" /* prototypes */ @@ -190,6 +192,8 @@ gst_dirac_parse_finalize (GObject * object) static gboolean gst_dirac_parse_start (GstBaseParse * parse) { + gst_base_parse_set_min_frame_size (parse, 13); + return TRUE; } @@ -206,102 +210,133 @@ gst_dirac_parse_set_sink_caps (GstBaseParse * parse, GstCaps * caps) 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 lost_sync; - gboolean draining; + guint8 *data; + int size; + gboolean have_picture = FALSE; + int offset; - if (G_UNLIKELY (GST_BUFFER_SIZE (frame->buffer) < 13)) + data = GST_BUFFER_DATA (frame->buffer); + size = GST_BUFFER_SIZE (frame->buffer); + + if (G_UNLIKELY (size < 13)) return FALSE; - off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff, - 0x42424344, 0, GST_BUFFER_SIZE (frame->buffer)); + GST_DEBUG ("%d: %02x %02x %02x %02x", size, data[0], data[1], data[2], + data[3]); - if (off < 0) { - *skipsize = GST_BUFFER_SIZE (frame->buffer) - 3; - return FALSE; - } + if (GST_READ_UINT32_BE (data) != 0x42424344) { + off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff, + 0x42424344, 0, GST_BUFFER_SIZE (frame->buffer)); - GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off); + if (off < 0) { + *skipsize = GST_BUFFER_SIZE (frame->buffer) - 3; + return FALSE; + } - if (off > 0) { - GST_ERROR ("skipping %d", off); + GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off); + + GST_DEBUG ("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; - } + /* have sync, parse chunks */ - GST_LOG ("framesize %d", *framesize); + offset = 0; + while (!have_picture) { + GST_DEBUG ("offset %d:", offset); - lost_sync = GST_BASE_PARSE_LOST_SYNC (frame); - draining = GST_BASE_PARSE_DRAINING (frame); - - if (lost_sync && !draining) { - guint32 next_sync_word = 0; - - 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; + if (offset + 13 >= size) { + *framesize = offset + 13; return FALSE; - } else { - if (next_sync_word != 0x42424344) { - *skipsize = 3; - return FALSE; - } else { - gst_base_parse_set_min_frame_size (parse, next_header); + } - } + GST_DEBUG ("chunk type %02x", data[offset + 4]); + + if (GST_READ_UINT32_BE (data + offset) != 0x42424344) { + GST_DEBUG ("bad header"); + *skipsize = 3; + return FALSE; + } + + next_header = GST_READ_UINT32_BE (data + offset + 5); + GST_DEBUG ("next_header %d", next_header); + if (next_header == 0) + next_header = 13; + + if (SCHRO_PARSE_CODE_IS_PICTURE (data[offset + 4])) { + have_picture = TRUE; + } + + offset += next_header; + if (offset >= size) { + *framesize = offset; + return FALSE; } } + *framesize = offset; + GST_DEBUG ("framesize %d", *framesize); + return TRUE; } static GstFlowReturn gst_dirac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { - //GstDiracParse * diracparse = GST_DIRAC_PARSE (parse); + GstDiracParse *diracparse = GST_DIRAC_PARSE (parse); + guint8 *data; + int size; /* 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); + data = GST_BUFFER_DATA (frame->buffer); + size = GST_BUFFER_SIZE (frame->buffer); - gst_buffer_set_caps (frame->buffer, caps); - gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps); - gst_caps_unref (caps); + //GST_ERROR("got here %d", size); + if (data[4] == SCHRO_PARSE_CODE_SEQUENCE_HEADER) { + GstCaps *caps; + DiracSequenceHeader sequence_header; + int ret; + + ret = dirac_sequence_header_parse (&sequence_header, data + 13, size - 13); + if (ret) { + memcpy (&diracparse->sequence_header, &sequence_header, + sizeof (sequence_header)); + caps = gst_caps_new_simple ("video/x-dirac", + "width", G_TYPE_INT, sequence_header.width, + "height", G_TYPE_INT, sequence_header.height, + "framerate", GST_TYPE_FRACTION, + sequence_header.frame_rate_numerator, + sequence_header.frame_rate_denominator, + "pixel-aspect-ratio", GST_TYPE_FRACTION, + sequence_header.aspect_ratio_numerator, + sequence_header.aspect_ratio_denominator, + "interlaced", G_TYPE_BOOLEAN, sequence_header.interlaced, + "profile", G_TYPE_INT, sequence_header.profile, + "level", G_TYPE_INT, sequence_header.level, NULL); + gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps); + gst_caps_unref (caps); + + gst_base_parse_set_frame_rate (parse, + sequence_header.frame_rate_numerator, + sequence_header.frame_rate_denominator, 0, 0); + } } + gst_buffer_set_caps (frame->buffer, + GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (parse))); + gst_base_parse_set_min_frame_size (parse, 13); return GST_FLOW_OK; diff --git a/gst/videoparsers/gstdiracparse.h b/gst/videoparsers/gstdiracparse.h index abf3821f15..7691c5790a 100644 --- a/gst/videoparsers/gstdiracparse.h +++ b/gst/videoparsers/gstdiracparse.h @@ -22,6 +22,7 @@ #include #include +#include "dirac_parse.h" G_BEGIN_DECLS @@ -38,6 +39,9 @@ struct _GstDiracParse { GstBaseParse base_diracparse; + DiracSequenceHeader sequence_header; + + guint32 frame_number; }; struct _GstDiracParseClass