1/*
2 * MJPEG parser
3 * Copyright (c) 2000, 2001 Fabrice Bellard
4 * Copyright (c) 2003 Alex Beregszaszi
5 * Copyright (c) 2003-2004 Michael Niedermayer
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24/**
25 * @file
26 * MJPEG parser.
27 */
28
29#include "parser.h"
30
31
32/**
33 * finds the end of the current frame in the bitstream.
34 * @return the position of the first byte of the next frame, or -1
35 */
36static int find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size){
37    int vop_found, i;
38    uint16_t state;
39
40    vop_found= pc->frame_start_found;
41    state= pc->state;
42
43    i=0;
44    if(!vop_found){
45        for(i=0; i<buf_size; i++){
46            state= (state<<8) | buf[i];
47            if(state == 0xFFD8){
48                i++;
49                vop_found=1;
50                break;
51            }
52        }
53    }
54
55    if(vop_found){
56        /* EOF considered as end of frame */
57        if (buf_size == 0)
58            return 0;
59        for(; i<buf_size; i++){
60            state= (state<<8) | buf[i];
61            if(state == 0xFFD8){
62                pc->frame_start_found=0;
63                pc->state=0;
64                return i-1;
65            }
66        }
67    }
68    pc->frame_start_found= vop_found;
69    pc->state= state;
70    return END_NOT_FOUND;
71}
72
73static int jpeg_parse(AVCodecParserContext *s,
74                      AVCodecContext *avctx,
75                      const uint8_t **poutbuf, int *poutbuf_size,
76                      const uint8_t *buf, int buf_size)
77{
78    ParseContext *pc = s->priv_data;
79    int next;
80
81    if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){
82        next= buf_size;
83    }else{
84        next= find_frame_end(pc, buf, buf_size);
85
86        if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
87            *poutbuf = NULL;
88            *poutbuf_size = 0;
89            return buf_size;
90        }
91    }
92
93    *poutbuf = buf;
94    *poutbuf_size = buf_size;
95    return next;
96}
97
98
99AVCodecParser mjpeg_parser = {
100    { CODEC_ID_MJPEG },
101    sizeof(ParseContext),
102    NULL,
103    jpeg_parse,
104    ff_parse_close,
105};
106