GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/mjpeg_parser.c Lines: 8 59 13.6 %
Date: 2019-11-20 04:07:19 Branches: 1 44 2.3 %

Line Branch Exec Source
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
typedef struct MJPEGParserContext{
32
    ParseContext pc;
33
    int size;
34
}MJPEGParserContext;
35
36
/**
37
 * Find the end of the current frame in the bitstream.
38
 * @return the position of the first byte of the next frame, or -1
39
 */
40
static int find_frame_end(MJPEGParserContext *m, const uint8_t *buf, int buf_size){
41
    ParseContext *pc= &m->pc;
42
    int vop_found, i;
43
    uint32_t state;
44
45
    vop_found= pc->frame_start_found;
46
    state= pc->state;
47
48
    i=0;
49
    if(!vop_found){
50
        for(i=0; i<buf_size;){
51
            state= (state<<8) | buf[i];
52
            if(state>=0xFFC00000 && state<=0xFFFEFFFF){
53
                if(state>=0xFFD8FFC0 && state<=0xFFD8FFFF){
54
                    i++;
55
                    vop_found=1;
56
                    break;
57
                }else if(state<0xFFD00000 || state>0xFFD9FFFF){
58
                    m->size= (state&0xFFFF)-1;
59
                }
60
            }
61
            if(m->size>0){
62
                int size= FFMIN(buf_size-i, m->size);
63
                i+=size;
64
                m->size-=size;
65
                state=0;
66
                continue;
67
            }else
68
                i++;
69
        }
70
    }
71
72
    if(vop_found){
73
        /* EOF considered as end of frame */
74
        if (buf_size == 0)
75
            return 0;
76
        for(; i<buf_size;){
77
            state= (state<<8) | buf[i];
78
            if(state>=0xFFC00000 && state<=0xFFFEFFFF){
79
                if(state>=0xFFD8FFC0 && state<=0xFFD8FFFF){
80
                    pc->frame_start_found=0;
81
                    pc->state=0;
82
                    return i-3;
83
                } else if(state<0xFFD00000 || state>0xFFD9FFFF){
84
                    m->size= (state&0xFFFF)-1;
85
                    if (m->size >= 0x8000)
86
                        m->size = 0;
87
                }
88
            }
89
            if(m->size>0){
90
                int size= FFMIN(buf_size-i, m->size);
91
                i+=size;
92
                m->size-=size;
93
                state=0;
94
                continue;
95
            }else
96
                i++;
97
        }
98
    }
99
    pc->frame_start_found= vop_found;
100
    pc->state= state;
101
    return END_NOT_FOUND;
102
}
103
104
1714
static int jpeg_parse(AVCodecParserContext *s,
105
                      AVCodecContext *avctx,
106
                      const uint8_t **poutbuf, int *poutbuf_size,
107
                      const uint8_t *buf, int buf_size)
108
{
109
1714
    MJPEGParserContext *m = s->priv_data;
110
1714
    ParseContext *pc = &m->pc;
111
    int next;
112
113
1714
    if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){
114
1714
        next= buf_size;
115
    }else{
116
        next= find_frame_end(m, buf, buf_size);
117
118
        if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
119
            *poutbuf = NULL;
120
            *poutbuf_size = 0;
121
            return buf_size;
122
        }
123
    }
124
125
1714
    *poutbuf = buf;
126
1714
    *poutbuf_size = buf_size;
127
1714
    return next;
128
}
129
130
131
AVCodecParser ff_mjpeg_parser = {
132
    .codec_ids      = { AV_CODEC_ID_MJPEG, AV_CODEC_ID_JPEGLS },
133
    .priv_data_size = sizeof(MJPEGParserContext),
134
    .parser_parse   = jpeg_parse,
135
    .parser_close   = ff_parse_close,
136
};