From 9c057b001e8873861a70f7025214003837a0860b Mon Sep 17 00:00:00 2001 From: Kamil Debski Date: Thu, 22 Mar 2012 09:36:27 +0100 Subject: v4l-mfc-example: version 0.2 --- v4l2-mfc-example/parser.c | 178 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 173 insertions(+), 5 deletions(-) (limited to 'v4l2-mfc-example/parser.c') 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; +} + -- cgit v1.2.3