diracparse: make diracparse work correctly

This commit is contained in:
David Schleef 2011-07-04 16:18:18 -07:00
parent ab1e013bb8
commit f21e36b54b
2 changed files with 96 additions and 57 deletions

View file

@ -36,7 +36,9 @@
#include <gst/gst.h>
#include <gst/base/gstbytereader.h>
#include <string.h>
#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;

View file

@ -22,6 +22,7 @@
#include <gst/gst.h>
#include <gst/base/gstbaseparse.h>
#include "dirac_parse.h"
G_BEGIN_DECLS
@ -38,6 +39,9 @@ struct _GstDiracParse
{
GstBaseParse base_diracparse;
DiracSequenceHeader sequence_header;
guint32 frame_number;
};
struct _GstDiracParseClass