annotate dca_parser.c @ 11245:1e9ff636c3db libavcodec

Make Bink decoder to stop decoding planes after all bits are used. This prevents crashes during decoding grayscale Bink files like samples from Impossible Creatures game demo.
author kostya
date Mon, 22 Feb 2010 12:35:12 +0000
parents e9d9d946f213
children 7dd2a45249a9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
1 /*
4899
e153b9ff47d3 Move dca parser to its own file.
diego
parents: 4895
diff changeset
2 * DCA parser
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
3 * Copyright (C) 2004 Gildas Bazin
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
4 * Copyright (C) 2004 Benjamin Zores
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
5 * Copyright (C) 2006 Benjamin Larsson
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
6 * Copyright (C) 2007 Konstantin Shishkov
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
7 *
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
8 * This file is part of FFmpeg.
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
9 *
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
10 * FFmpeg is free software; you can redistribute it and/or
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
11 * modify it under the terms of the GNU Lesser General Public
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
12 * License as published by the Free Software Foundation; either
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
13 * version 2.1 of the License, or (at your option) any later version.
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
14 *
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
15 * FFmpeg is distributed in the hope that it will be useful,
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
18 * Lesser General Public License for more details.
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
19 *
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
20 * You should have received a copy of the GNU Lesser General Public
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
21 * License along with FFmpeg; if not, write to the Free Software
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
23 */
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
24
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
25 /**
8718
e9d9d946f213 Use full internal pathname in doxygen @file directives.
diego
parents: 8226
diff changeset
26 * @file libavcodec/dca_parser.c
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
27 */
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
28
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
29 #include "parser.h"
4899
e153b9ff47d3 Move dca parser to its own file.
diego
parents: 4895
diff changeset
30 #include "dca.h"
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
31
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
32 typedef struct DCAParseContext {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
33 ParseContext pc;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
34 uint32_t lastmarker;
6598
05987f234569 DCA frame size is constant
kostya
parents: 6517
diff changeset
35 int size;
05987f234569 DCA frame size is constant
kostya
parents: 6517
diff changeset
36 int framesize;
8226
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
37 int hd_pos;
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
38 } DCAParseContext;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
39
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
40 #define IS_MARKER(state, i, buf, buf_size) \
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
41 ((state == DCA_MARKER_14B_LE && (i < buf_size-2) && (buf[i+1] & 0xF0) == 0xF0 && buf[i+2] == 0x07) \
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
42 || (state == DCA_MARKER_14B_BE && (i < buf_size-2) && buf[i+1] == 0x07 && (buf[i+2] & 0xF0) == 0xF0) \
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
43 || state == DCA_MARKER_RAW_LE || state == DCA_MARKER_RAW_BE)
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
44
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
45 /**
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
46 * finds the end of the current frame in the bitstream.
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
47 * @return the position of the first byte of the next frame, or -1
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
48 */
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
49 static int dca_find_frame_end(DCAParseContext * pc1, const uint8_t * buf,
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
50 int buf_size)
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
51 {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
52 int start_found, i;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
53 uint32_t state;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
54 ParseContext *pc = &pc1->pc;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
55
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
56 start_found = pc->frame_start_found;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
57 state = pc->state;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
58
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
59 i = 0;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
60 if (!start_found) {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
61 for (i = 0; i < buf_size; i++) {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
62 state = (state << 8) | buf[i];
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
63 if (IS_MARKER(state, i, buf, buf_size)) {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
64 if (pc1->lastmarker && state == pc1->lastmarker) {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
65 start_found = 1;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
66 break;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
67 } else if (!pc1->lastmarker) {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
68 start_found = 1;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
69 pc1->lastmarker = state;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
70 break;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
71 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
72 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
73 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
74 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
75 if (start_found) {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
76 for (; i < buf_size; i++) {
6598
05987f234569 DCA frame size is constant
kostya
parents: 6517
diff changeset
77 pc1->size++;
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
78 state = (state << 8) | buf[i];
8226
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
79 if (state == DCA_HD_MARKER && !pc1->hd_pos)
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
80 pc1->hd_pos = pc1->size;
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
81 if (state == pc1->lastmarker && IS_MARKER(state, i, buf, buf_size)) {
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
82 if(pc1->framesize > pc1->size)
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
83 continue;
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
84 if(!pc1->framesize){
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
85 pc1->framesize = pc1->hd_pos ? pc1->hd_pos : pc1->size;
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
86 }
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
87 pc->frame_start_found = 0;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
88 pc->state = -1;
6598
05987f234569 DCA frame size is constant
kostya
parents: 6517
diff changeset
89 pc1->size = 0;
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
90 return i - 3;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
91 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
92 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
93 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
94 pc->frame_start_found = start_found;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
95 pc->state = state;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
96 return END_NOT_FOUND;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
97 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
98
6517
48759bfbd073 Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents: 4931
diff changeset
99 static av_cold int dca_parse_init(AVCodecParserContext * s)
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
100 {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
101 DCAParseContext *pc1 = s->priv_data;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
102
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
103 pc1->lastmarker = 0;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
104 return 0;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
105 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
106
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
107 static int dca_parse(AVCodecParserContext * s,
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
108 AVCodecContext * avctx,
4931
0d1cc37d9430 make some parser parameters const to avoid casting const to non-const
aurel
parents: 4919
diff changeset
109 const uint8_t ** poutbuf, int *poutbuf_size,
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
110 const uint8_t * buf, int buf_size)
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
111 {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
112 DCAParseContext *pc1 = s->priv_data;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
113 ParseContext *pc = &pc1->pc;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
114 int next;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
115
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
116 if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
117 next = buf_size;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
118 } else {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
119 next = dca_find_frame_end(pc1, buf, buf_size);
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
120
4931
0d1cc37d9430 make some parser parameters const to avoid casting const to non-const
aurel
parents: 4919
diff changeset
121 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
122 *poutbuf = NULL;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
123 *poutbuf_size = 0;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
124 return buf_size;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
125 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
126 }
4931
0d1cc37d9430 make some parser parameters const to avoid casting const to non-const
aurel
parents: 4919
diff changeset
127 *poutbuf = buf;
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
128 *poutbuf_size = buf_size;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
129 return next;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
130 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
131
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
132 AVCodecParser dca_parser = {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
133 {CODEC_ID_DTS},
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
134 sizeof(DCAParseContext),
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
135 dca_parse_init,
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
136 dca_parse,
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
137 ff_parse_close,
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
138 };