Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/mpegvideo_parser.c')
-rw-r--r--libavcodec/mpegvideo_parser.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c
index 7864224643..39b9f2e43a 100644
--- a/libavcodec/mpegvideo_parser.c
+++ b/libavcodec/mpegvideo_parser.c
@@ -31,6 +31,72 @@ struct MpvParseContext {
int width, height;
};
+#if !FF_API_FLAG_TRUNCATED
+/**
+ * Find the end of the current frame in the bitstream.
+ * @return the position of the first byte of the next frame, or -1
+ */
+static int mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf,
+ int buf_size, AVCodecParserContext *s)
+{
+ int i;
+ uint32_t state = pc->state;
+
+ /* EOF considered as end of frame */
+ if (buf_size == 0)
+ return 0;
+
+/*
+ 0 frame start -> 1/4
+ 1 first_SEQEXT -> 0/2
+ 2 first field start -> 3/0
+ 3 second_SEQEXT -> 2/0
+ 4 searching end
+*/
+
+ for (i = 0; i < buf_size; i++) {
+ av_assert1(pc->frame_start_found >= 0 && pc->frame_start_found <= 4);
+ if (pc->frame_start_found & 1) {
+ if (state == EXT_START_CODE && (buf[i] & 0xF0) != 0x80)
+ pc->frame_start_found--;
+ else if (state == EXT_START_CODE + 2) {
+ if ((buf[i] & 3) == 3)
+ pc->frame_start_found = 0;
+ else
+ pc->frame_start_found = (pc->frame_start_found + 1) & 3;
+ }
+ state++;
+ } else {
+ i = avpriv_find_start_code(buf + i, buf + buf_size, &state) - buf - 1;
+ if (pc->frame_start_found == 0 && state >= SLICE_MIN_START_CODE && state <= SLICE_MAX_START_CODE) {
+ i++;
+ pc->frame_start_found = 4;
+ }
+ if (state == SEQ_END_CODE) {
+ pc->frame_start_found = 0;
+ pc->state = -1;
+ return i + 1;
+ }
+ if (pc->frame_start_found == 2 && state == SEQ_START_CODE)
+ pc->frame_start_found = 0;
+ if (pc->frame_start_found < 4 && state == EXT_START_CODE)
+ pc->frame_start_found++;
+ if (pc->frame_start_found == 4 && (state & 0xFFFFFF00) == 0x100) {
+ if (state < SLICE_MIN_START_CODE || state > SLICE_MAX_START_CODE) {
+ pc->frame_start_found = 0;
+ pc->state = -1;
+ return i - 3;
+ }
+ }
+ if (pc->frame_start_found == 0 && s && state == PICTURE_START_CODE) {
+ ff_fetch_timestamp(s, i - 3, 1, i > 3);
+ }
+ }
+ }
+ pc->state = state;
+ return END_NOT_FOUND;
+}
+#endif
static void mpegvideo_extract_headers(AVCodecParserContext *s,
AVCodecContext *avctx,
@@ -192,7 +258,11 @@ static int mpegvideo_parse(AVCodecParserContext *s,
if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){
next= buf_size;
}else{
+#if FF_API_FLAG_TRUNCATED
next= ff_mpeg1_find_frame_end(pc, buf, buf_size, s);
+#else
+ next = mpeg1_find_frame_end(pc, buf, buf_size, s);
+#endif
if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
*poutbuf = NULL;