Mercurial > libavcodec.hg
annotate h264_mp4toannexb_bsf.c @ 12483:0159a19bfff7 libavcodec
aacdec: Rework channel mapping compatibility hacks.
For a PCE based configuration map the channels solely based on tags.
For an indexed configuration map the channels solely based on position.
This works with all known exotic samples including al17, elem_id0, bad_concat,
and lfe_is_sce.
author | alexc |
---|---|
date | Fri, 10 Sep 2010 18:01:48 +0000 |
parents | b39ced9e4fc3 |
children |
rev | line source |
---|---|
5644 | 1 /* |
9632 | 2 * H.264 MP4 to Annex B byte stream format filter |
8156 | 3 * Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr> |
5644 | 4 * |
5 * This file is part of FFmpeg. | |
6 * | |
7 * FFmpeg is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Lesser General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2.1 of the License, or (at your option) any later version. | |
11 * | |
12 * FFmpeg is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
18 * License along with FFmpeg; if not, write to the Free Software | |
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 */ | |
21 | |
8573
2acf0ae7b041
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
8156
diff
changeset
|
22 #include "libavutil/intreadwrite.h" |
5644 | 23 #include "avcodec.h" |
24 | |
25 typedef struct H264BSFContext { | |
26 uint8_t length_size; | |
27 uint8_t first_idr; | |
11857
e1e986bb64d0
Improve the mp4toannexb BSF to convert the extradata.
lucabe
parents:
11698
diff
changeset
|
28 int extradata_parsed; |
5644 | 29 } H264BSFContext; |
30 | |
11858
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
31 static int alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size, |
11860 | 32 const uint8_t *sps_pps, uint32_t sps_pps_size, |
33 const uint8_t *in, uint32_t in_size) { | |
5644 | 34 uint32_t offset = *poutbuf_size; |
35 uint8_t nal_header_size = offset ? 3 : 4; | |
11858
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
36 void *tmp; |
5644 | 37 |
38 *poutbuf_size += sps_pps_size+in_size+nal_header_size; | |
11858
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
39 tmp = av_realloc(*poutbuf, *poutbuf_size); |
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
40 if (!tmp) |
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
41 return AVERROR(ENOMEM); |
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
42 *poutbuf = tmp; |
5644 | 43 if (sps_pps) |
44 memcpy(*poutbuf+offset, sps_pps, sps_pps_size); | |
45 memcpy(*poutbuf+sps_pps_size+nal_header_size+offset, in, in_size); | |
11859
f533ea0b236f
Cosmetics: use and place braces correctly in if ... else statements.
benoit
parents:
11858
diff
changeset
|
46 if (!offset) { |
5644 | 47 AV_WB32(*poutbuf+sps_pps_size, 1); |
11859
f533ea0b236f
Cosmetics: use and place braces correctly in if ... else statements.
benoit
parents:
11858
diff
changeset
|
48 } else { |
6134
6d0c5a68d559
Fix a bug causing the generated stream to be corrupt if the buffer
andoma
parents:
5644
diff
changeset
|
49 (*poutbuf+offset+sps_pps_size)[0] = (*poutbuf+offset+sps_pps_size)[1] = 0; |
6d0c5a68d559
Fix a bug causing the generated stream to be corrupt if the buffer
andoma
parents:
5644
diff
changeset
|
50 (*poutbuf+offset+sps_pps_size)[2] = 1; |
5644 | 51 } |
11858
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
52 |
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
53 return 0; |
5644 | 54 } |
55 | |
56 static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc, | |
57 AVCodecContext *avctx, const char *args, | |
58 uint8_t **poutbuf, int *poutbuf_size, | |
59 const uint8_t *buf, int buf_size, | |
60 int keyframe) { | |
61 H264BSFContext *ctx = bsfc->priv_data; | |
62 uint8_t unit_type; | |
11698
9a4c9c165b3b
Check NAL unit size to avoid reading past the buffer.
benoit
parents:
9632
diff
changeset
|
63 int32_t nal_size; |
9a4c9c165b3b
Check NAL unit size to avoid reading past the buffer.
benoit
parents:
9632
diff
changeset
|
64 uint32_t cumul_size = 0; |
9a4c9c165b3b
Check NAL unit size to avoid reading past the buffer.
benoit
parents:
9632
diff
changeset
|
65 const uint8_t *buf_end = buf + buf_size; |
5644 | 66 |
67 /* nothing to filter */ | |
68 if (!avctx->extradata || avctx->extradata_size < 6) { | |
69 *poutbuf = (uint8_t*) buf; | |
70 *poutbuf_size = buf_size; | |
71 return 0; | |
72 } | |
73 | |
74 /* retrieve sps and pps NAL units from extradata */ | |
11857
e1e986bb64d0
Improve the mp4toannexb BSF to convert the extradata.
lucabe
parents:
11698
diff
changeset
|
75 if (!ctx->extradata_parsed) { |
5644 | 76 uint16_t unit_size; |
11857
e1e986bb64d0
Improve the mp4toannexb BSF to convert the extradata.
lucabe
parents:
11698
diff
changeset
|
77 uint64_t total_size = 0; |
5644 | 78 uint8_t *out = NULL, unit_nb, sps_done = 0; |
79 const uint8_t *extradata = avctx->extradata+4; | |
80 static const uint8_t nalu_header[4] = {0, 0, 0, 1}; | |
81 | |
82 /* retrieve length coded size */ | |
83 ctx->length_size = (*extradata++ & 0x3) + 1; | |
84 if (ctx->length_size == 3) | |
85 return AVERROR(EINVAL); | |
86 | |
87 /* retrieve sps and pps unit(s) */ | |
88 unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */ | |
89 if (!unit_nb) { | |
90 unit_nb = *extradata++; /* number of pps unit(s) */ | |
91 sps_done++; | |
92 } | |
93 while (unit_nb--) { | |
11858
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
94 void *tmp; |
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
95 |
5644 | 96 unit_size = AV_RB16(extradata); |
97 total_size += unit_size+4; | |
11860 | 98 if (total_size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE || |
99 extradata+2+unit_size > avctx->extradata+avctx->extradata_size) { | |
5644 | 100 av_free(out); |
101 return AVERROR(EINVAL); | |
102 } | |
11858
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
103 tmp = av_realloc(out, total_size + FF_INPUT_BUFFER_PADDING_SIZE); |
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
104 if (!tmp) { |
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
105 av_free(out); |
5644 | 106 return AVERROR(ENOMEM); |
11858
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
107 } |
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
108 out = tmp; |
5644 | 109 memcpy(out+total_size-unit_size-4, nalu_header, 4); |
110 memcpy(out+total_size-unit_size, extradata+2, unit_size); | |
111 extradata += 2+unit_size; | |
112 | |
113 if (!unit_nb && !sps_done++) | |
114 unit_nb = *extradata++; /* number of pps unit(s) */ | |
115 } | |
116 | |
11857
e1e986bb64d0
Improve the mp4toannexb BSF to convert the extradata.
lucabe
parents:
11698
diff
changeset
|
117 memset(out + total_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); |
e1e986bb64d0
Improve the mp4toannexb BSF to convert the extradata.
lucabe
parents:
11698
diff
changeset
|
118 av_free(avctx->extradata); |
e1e986bb64d0
Improve the mp4toannexb BSF to convert the extradata.
lucabe
parents:
11698
diff
changeset
|
119 avctx->extradata = out; |
e1e986bb64d0
Improve the mp4toannexb BSF to convert the extradata.
lucabe
parents:
11698
diff
changeset
|
120 avctx->extradata_size = total_size; |
e1e986bb64d0
Improve the mp4toannexb BSF to convert the extradata.
lucabe
parents:
11698
diff
changeset
|
121 ctx->first_idr = 1; |
e1e986bb64d0
Improve the mp4toannexb BSF to convert the extradata.
lucabe
parents:
11698
diff
changeset
|
122 ctx->extradata_parsed = 1; |
5644 | 123 } |
124 | |
125 *poutbuf_size = 0; | |
126 *poutbuf = NULL; | |
127 do { | |
11698
9a4c9c165b3b
Check NAL unit size to avoid reading past the buffer.
benoit
parents:
9632
diff
changeset
|
128 if (buf + ctx->length_size > buf_end) |
9a4c9c165b3b
Check NAL unit size to avoid reading past the buffer.
benoit
parents:
9632
diff
changeset
|
129 goto fail; |
9a4c9c165b3b
Check NAL unit size to avoid reading past the buffer.
benoit
parents:
9632
diff
changeset
|
130 |
11859
f533ea0b236f
Cosmetics: use and place braces correctly in if ... else statements.
benoit
parents:
11858
diff
changeset
|
131 if (ctx->length_size == 1) { |
5644 | 132 nal_size = buf[0]; |
11859
f533ea0b236f
Cosmetics: use and place braces correctly in if ... else statements.
benoit
parents:
11858
diff
changeset
|
133 } else if (ctx->length_size == 2) { |
5644 | 134 nal_size = AV_RB16(buf); |
11859
f533ea0b236f
Cosmetics: use and place braces correctly in if ... else statements.
benoit
parents:
11858
diff
changeset
|
135 } else |
5644 | 136 nal_size = AV_RB32(buf); |
137 | |
138 buf += ctx->length_size; | |
139 unit_type = *buf & 0x1f; | |
140 | |
11698
9a4c9c165b3b
Check NAL unit size to avoid reading past the buffer.
benoit
parents:
9632
diff
changeset
|
141 if (buf + nal_size > buf_end || nal_size < 0) |
9a4c9c165b3b
Check NAL unit size to avoid reading past the buffer.
benoit
parents:
9632
diff
changeset
|
142 goto fail; |
9a4c9c165b3b
Check NAL unit size to avoid reading past the buffer.
benoit
parents:
9632
diff
changeset
|
143 |
5644 | 144 /* prepend only to the first type 5 NAL unit of an IDR picture */ |
145 if (ctx->first_idr && unit_type == 5) { | |
11858
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
146 if (alloc_and_copy(poutbuf, poutbuf_size, |
11860 | 147 avctx->extradata, avctx->extradata_size, |
11858
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
148 buf, nal_size) < 0) |
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
149 goto fail; |
5644 | 150 ctx->first_idr = 0; |
11859
f533ea0b236f
Cosmetics: use and place braces correctly in if ... else statements.
benoit
parents:
11858
diff
changeset
|
151 } else { |
11858
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
152 if (alloc_and_copy(poutbuf, poutbuf_size, |
11860 | 153 NULL, 0, |
11858
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
154 buf, nal_size) < 0) |
fb5a6e98aa1c
Sanitize av_realloc() use in h264 mp4toannexb bistream filter.
benoit
parents:
11857
diff
changeset
|
155 goto fail; |
5644 | 156 if (!ctx->first_idr && unit_type == 1) |
157 ctx->first_idr = 1; | |
158 } | |
159 | |
160 buf += nal_size; | |
161 cumul_size += nal_size + ctx->length_size; | |
162 } while (cumul_size < buf_size); | |
163 | |
164 return 1; | |
11698
9a4c9c165b3b
Check NAL unit size to avoid reading past the buffer.
benoit
parents:
9632
diff
changeset
|
165 |
9a4c9c165b3b
Check NAL unit size to avoid reading past the buffer.
benoit
parents:
9632
diff
changeset
|
166 fail: |
9a4c9c165b3b
Check NAL unit size to avoid reading past the buffer.
benoit
parents:
9632
diff
changeset
|
167 av_freep(poutbuf); |
9a4c9c165b3b
Check NAL unit size to avoid reading past the buffer.
benoit
parents:
9632
diff
changeset
|
168 *poutbuf_size = 0; |
9a4c9c165b3b
Check NAL unit size to avoid reading past the buffer.
benoit
parents:
9632
diff
changeset
|
169 return AVERROR(EINVAL); |
5644 | 170 } |
171 | |
172 AVBitStreamFilter h264_mp4toannexb_bsf = { | |
173 "h264_mp4toannexb", | |
174 sizeof(H264BSFContext), | |
175 h264_mp4toannexb_filter, | |
176 }; | |
177 |