summaryrefslogtreecommitdiff
path: root/v4l2-mfc-example/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'v4l2-mfc-example/parser.c')
-rw-r--r--v4l2-mfc-example/parser.c178
1 files changed, 173 insertions, 5 deletions
diff --git a/v4l2-mfc-example/parser.c b/v4l2-mfc-example/parser.c
index 6691dd1..4fd84db 100644
--- a/v4l2-mfc-example/parser.c
+++ b/v4l2-mfc-example/parser.c
@@ -68,10 +68,23 @@ int parse_mpeg4_stream(
if (*in == 0x1) {
ctx->state = MPEG4_PARSER_CODE_1x1;
} else if ((*in & 0xFC) == 0x80) {
- // Short header
+ /* Short header */
ctx->state = MPEG4_PARSER_NO_CODE;
- ctx->last_tag = MPEG4_TAG_HEAD;
- ctx->main_count++;
+ /* Ignore the short header if the current hasn't
+ * been started with a short header. */
+
+ if (get_head && !ctx->short_header) {
+ ctx->last_tag = MPEG4_TAG_HEAD;
+ ctx->headers_count++;
+ ctx->short_header = 1;
+ } else if (!ctx->seek_end ||
+ (ctx->seek_end && ctx->short_header)) {
+ ctx->last_tag = MPEG4_TAG_VOP;
+ ctx->main_count++;
+ ctx->short_header = 1;
+ }
+ } else if (*in == 0x0) {
+ ctx->tmp_code_start++;
} else {
ctx->state = MPEG4_PARSER_NO_CODE;
}
@@ -93,7 +106,7 @@ int parse_mpeg4_stream(
break;
}
- if (get_head == 1 && ctx->headers_count > 1 && ctx->main_count == 1) {
+ if (get_head == 1 && ctx->headers_count >= 1 && ctx->main_count == 1) {
ctx->code_end = ctx->tmp_code_start;
ctx->got_end = 1;
break;
@@ -174,6 +187,10 @@ int parse_mpeg4_stream(
ctx->seek_end = 0;
ctx->main_count = 0;
ctx->headers_count = 1;
+ ctx->short_header = 0;
+ /* If the last frame used the short then
+ * we shall save this information, otherwise
+ * it is necessary to clear it */
}
memcpy(ctx->bytes, in_orig + ctx->code_end, *consumed - ctx->code_end);
} else {
@@ -229,6 +246,8 @@ int parse_h264_stream(
case H264_PARSER_CODE_0x3:
if (*in == 0x1)
ctx->state = H264_PARSER_CODE_1x1;
+ else if (*in == 0x0)
+ ctx->tmp_code_start++;
else
ctx->state = H264_PARSER_NO_CODE;
break;
@@ -254,7 +273,7 @@ int parse_h264_stream(
break;
}
- if (get_head == 1 && ctx->headers_count > 1 && ctx->main_count == 1) {
+ if (get_head == 1 && ctx->headers_count >= 1 && ctx->main_count == 1) {
ctx->code_end = ctx->tmp_code_start;
ctx->got_end = 1;
break;
@@ -347,3 +366,152 @@ int parse_h264_stream(
return frame_finished;
}
+int parse_mpeg2_stream(
+ struct mfc_parser_context *ctx,
+ char* in, int in_size, char* out, int out_size,
+ int *consumed, int *frame_size, char get_head)
+{
+ char *in_orig;
+ char frame_finished;
+ int frame_length;
+
+ in_orig = in;
+
+ *consumed = 0;
+
+ frame_finished = 0;
+
+ while (in_size-- > 0) {
+ switch (ctx->state) {
+ case MPEG4_PARSER_NO_CODE:
+ if (*in == 0x0) {
+ ctx->state = MPEG4_PARSER_CODE_0x1;
+ ctx->tmp_code_start = *consumed;
+ }
+ break;
+ case MPEG4_PARSER_CODE_0x1:
+ if (*in == 0x0)
+ ctx->state = MPEG4_PARSER_CODE_0x2;
+ else
+ ctx->state = MPEG4_PARSER_NO_CODE;
+ break;
+ case MPEG4_PARSER_CODE_0x2:
+ if (*in == 0x1) {
+ ctx->state = MPEG4_PARSER_CODE_1x1;
+ } else if (*in == 0x0) {
+ /* We still have two zeroes */
+ ctx->tmp_code_start++;
+ // TODO XXX check in h264 and mpeg4
+ } else {
+ ctx->state = MPEG4_PARSER_NO_CODE;
+ }
+ break;
+ case MPEG4_PARSER_CODE_1x1:
+ if (*in == 0xb3 || *in == 0xb8) {
+ ctx->state = MPEG4_PARSER_NO_CODE;
+ ctx->last_tag = MPEG4_TAG_HEAD;
+ ctx->headers_count++;
+ dbg("Found header at %d (%x)", *consumed, *consumed);
+ } else if (*in == 0x00) {
+ ctx->state = MPEG4_PARSER_NO_CODE;
+ ctx->last_tag = MPEG4_TAG_VOP;
+ ctx->main_count++;
+ dbg("Found picture at %d (%x)", *consumed, *consumed);
+ } else
+ ctx->state = MPEG4_PARSER_NO_CODE;
+ break;
+ }
+
+ if (get_head == 1 && ctx->headers_count >= 1 && ctx->main_count == 1) {
+ ctx->code_end = ctx->tmp_code_start;
+ ctx->got_end = 1;
+ break;
+ }
+
+ if (ctx->got_start == 0 && ctx->headers_count == 1 && ctx->main_count == 0) {
+ ctx->code_start = ctx->tmp_code_start;
+ ctx->got_start = 1;
+ }
+
+ if (ctx->got_start == 0 && ctx->headers_count == 0 && ctx->main_count == 1) {
+ ctx->code_start = ctx->tmp_code_start;
+ ctx->got_start = 1;
+ ctx->seek_end = 1;
+ ctx->headers_count = 0;
+ ctx->main_count = 0;
+ }
+
+ if (ctx->seek_end == 0 && ctx->headers_count > 0 && ctx->main_count == 1) {
+ ctx->seek_end = 1;
+ ctx->headers_count = 0;
+ ctx->main_count = 0;
+ }
+
+ if (ctx->seek_end == 1 && (ctx->headers_count > 0 || ctx->main_count > 0)) {
+ ctx->code_end = ctx->tmp_code_start;
+ ctx->got_end = 1;
+ if (ctx->headers_count == 0)
+ ctx->seek_end = 1;
+ else
+ ctx->seek_end = 0;
+ break;
+ }
+
+ in++;
+ (*consumed)++;
+ }
+
+ *frame_size = 0;
+
+ if (ctx->got_end == 1) {
+ frame_length = ctx->code_end;
+ } else
+ frame_length = *consumed;
+
+
+ if (ctx->code_start >= 0) {
+ frame_length -= ctx->code_start;
+ in = in_orig + ctx->code_start;
+ } else {
+ memcpy(out, ctx->bytes, -ctx->code_start);
+ *frame_size += -ctx->code_start;
+ out += -ctx->code_start;
+ in_size -= -ctx->code_start;
+ in = in_orig;
+ }
+
+ if (ctx->got_start) {
+ if (out_size < frame_length) {
+ err("Output buffer too small for current frame");
+ return 0;
+ }
+
+ memcpy(out, in, frame_length);
+ *frame_size += frame_length;
+
+ if (ctx->got_end) {
+ ctx->code_start = ctx->code_end - *consumed;
+ ctx->got_start = 1;
+ ctx->got_end = 0;
+ frame_finished = 1;
+ if (ctx->last_tag == MPEG4_TAG_VOP) {
+ ctx->seek_end = 1;
+ ctx->main_count = 0;
+ ctx->headers_count = 0;
+ } else {
+ ctx->seek_end = 0;
+ ctx->main_count = 0;
+ ctx->headers_count = 1;
+ }
+ memcpy(ctx->bytes, in_orig + ctx->code_end, *consumed - ctx->code_end);
+ } else {
+ ctx->code_start = 0;
+ frame_finished = 0;
+ }
+ }
+
+ ctx->tmp_code_start -= *consumed;
+
+ return frame_finished;
+}
+