annotate dca_parser.c @ 12329:6644e439130d libavcodec

Calculate an exact frame size before writing. Now the buffer size requirements can be known exactly, so larger frame sizes can be safely encoded without buffer overwrite.
author jbr
date Sat, 31 Jul 2010 20:32:12 +0000
parents 7dd2a45249a9
children
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 #include "parser.h"
4899
e153b9ff47d3 Move dca parser to its own file.
diego
parents: 4895
diff changeset
26 #include "dca.h"
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
27
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
28 typedef struct DCAParseContext {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
29 ParseContext pc;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
30 uint32_t lastmarker;
6598
05987f234569 DCA frame size is constant
kostya
parents: 6517
diff changeset
31 int size;
05987f234569 DCA frame size is constant
kostya
parents: 6517
diff changeset
32 int framesize;
8226
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
33 int hd_pos;
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
34 } DCAParseContext;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
35
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
36 #define IS_MARKER(state, i, buf, buf_size) \
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
37 ((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
38 || (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
39 || state == DCA_MARKER_RAW_LE || state == DCA_MARKER_RAW_BE)
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
40
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
41 /**
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
42 * finds the end of the current frame in the bitstream.
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
43 * @return the position of the first byte of the next frame, or -1
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
44 */
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
45 static int dca_find_frame_end(DCAParseContext * pc1, const uint8_t * buf,
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
46 int buf_size)
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
47 {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
48 int start_found, i;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
49 uint32_t state;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
50 ParseContext *pc = &pc1->pc;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
51
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
52 start_found = pc->frame_start_found;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
53 state = pc->state;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
54
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
55 i = 0;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
56 if (!start_found) {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
57 for (i = 0; i < buf_size; i++) {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
58 state = (state << 8) | buf[i];
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
59 if (IS_MARKER(state, i, buf, buf_size)) {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
60 if (pc1->lastmarker && state == pc1->lastmarker) {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
61 start_found = 1;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
62 break;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
63 } else if (!pc1->lastmarker) {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
64 start_found = 1;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
65 pc1->lastmarker = state;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
66 break;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
67 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
68 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
69 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
70 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
71 if (start_found) {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
72 for (; i < buf_size; i++) {
6598
05987f234569 DCA frame size is constant
kostya
parents: 6517
diff changeset
73 pc1->size++;
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
74 state = (state << 8) | buf[i];
8226
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
75 if (state == DCA_HD_MARKER && !pc1->hd_pos)
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
76 pc1->hd_pos = pc1->size;
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
77 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
78 if(pc1->framesize > pc1->size)
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
79 continue;
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
80 if(!pc1->framesize){
ee1b8c54a603 Add support for parsing and decoding DCA-HD streams.
kostya
parents: 6598
diff changeset
81 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
82 }
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
83 pc->frame_start_found = 0;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
84 pc->state = -1;
6598
05987f234569 DCA frame size is constant
kostya
parents: 6517
diff changeset
85 pc1->size = 0;
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
86 return i - 3;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
87 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
88 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
89 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
90 pc->frame_start_found = start_found;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
91 pc->state = state;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
92 return END_NOT_FOUND;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
93 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
94
6517
48759bfbd073 Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents: 4931
diff changeset
95 static av_cold int dca_parse_init(AVCodecParserContext * s)
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
96 {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
97 DCAParseContext *pc1 = s->priv_data;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
98
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
99 pc1->lastmarker = 0;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
100 return 0;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
101 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
102
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
103 static int dca_parse(AVCodecParserContext * s,
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
104 AVCodecContext * avctx,
4931
0d1cc37d9430 make some parser parameters const to avoid casting const to non-const
aurel
parents: 4919
diff changeset
105 const uint8_t ** poutbuf, int *poutbuf_size,
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
106 const uint8_t * buf, int buf_size)
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
107 {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
108 DCAParseContext *pc1 = s->priv_data;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
109 ParseContext *pc = &pc1->pc;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
110 int next;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
111
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
112 if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
113 next = buf_size;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
114 } else {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
115 next = dca_find_frame_end(pc1, buf, buf_size);
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
116
4931
0d1cc37d9430 make some parser parameters const to avoid casting const to non-const
aurel
parents: 4919
diff changeset
117 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
118 *poutbuf = NULL;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
119 *poutbuf_size = 0;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
120 return buf_size;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
121 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
122 }
4931
0d1cc37d9430 make some parser parameters const to avoid casting const to non-const
aurel
parents: 4919
diff changeset
123 *poutbuf = buf;
4599
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
124 *poutbuf_size = buf_size;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
125 return next;
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
126 }
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
127
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
128 AVCodecParser dca_parser = {
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
129 {CODEC_ID_DTS},
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
130 sizeof(DCAParseContext),
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
131 dca_parse_init,
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
132 dca_parse,
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
133 ff_parse_close,
2cd245d65761 DCA decoder
kostya
parents:
diff changeset
134 };