annotate h264_mp4toannexb_bsf.c @ 8520:a0164882aa38 libavcodec

Generic metadata API. avi is updated as example. No version bump, the API still might change slightly ... No update to ffmpeg.c as requested by aurel.
author michael
date Sun, 04 Jan 2009 18:48:37 +0000
parents a5e7dbce5412
children 2acf0ae7b041
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5644
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
1 /*
8156
a5e7dbce5412 Change email address to a valid one.
benoit
parents: 6134
diff changeset
2 * Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
5644
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
3 *
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
4 * This file is part of FFmpeg.
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
5 *
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
6 * FFmpeg is free software; you can redistribute it and/or
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
7 * modify it under the terms of the GNU Lesser General Public
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
8 * License as published by the Free Software Foundation; either
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
9 * version 2.1 of the License, or (at your option) any later version.
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
10 *
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
11 * FFmpeg is distributed in the hope that it will be useful,
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
14 * Lesser General Public License for more details.
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
15 *
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
16 * You should have received a copy of the GNU Lesser General Public
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
17 * License along with FFmpeg; if not, write to the Free Software
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
19 */
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
20
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
21 #include "avcodec.h"
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
22
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
23 typedef struct H264BSFContext {
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
24 uint8_t length_size;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
25 uint8_t first_idr;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
26 uint8_t *sps_pps_data;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
27 uint32_t size;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
28 } H264BSFContext;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
29
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
30 static void alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size,
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
31 const uint8_t *sps_pps, uint32_t sps_pps_size,
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
32 const uint8_t *in, uint32_t in_size) {
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
33 uint32_t offset = *poutbuf_size;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
34 uint8_t nal_header_size = offset ? 3 : 4;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
35
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
36 *poutbuf_size += sps_pps_size+in_size+nal_header_size;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
37 *poutbuf = av_realloc(*poutbuf, *poutbuf_size);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
38 if (sps_pps)
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
39 memcpy(*poutbuf+offset, sps_pps, sps_pps_size);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
40 memcpy(*poutbuf+sps_pps_size+nal_header_size+offset, in, in_size);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
41 if (!offset)
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
42 AV_WB32(*poutbuf+sps_pps_size, 1);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
43 else {
6134
6d0c5a68d559 Fix a bug causing the generated stream to be corrupt if the buffer
andoma
parents: 5644
diff changeset
44 (*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
45 (*poutbuf+offset+sps_pps_size)[2] = 1;
5644
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
46 }
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
47 }
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
48
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
49 static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
50 AVCodecContext *avctx, const char *args,
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
51 uint8_t **poutbuf, int *poutbuf_size,
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
52 const uint8_t *buf, int buf_size,
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
53 int keyframe) {
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
54 H264BSFContext *ctx = bsfc->priv_data;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
55 uint8_t unit_type;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
56 uint32_t nal_size, cumul_size = 0;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
57
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
58 /* nothing to filter */
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
59 if (!avctx->extradata || avctx->extradata_size < 6) {
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
60 *poutbuf = (uint8_t*) buf;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
61 *poutbuf_size = buf_size;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
62 return 0;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
63 }
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
64
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
65 /* retrieve sps and pps NAL units from extradata */
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
66 if (!ctx->sps_pps_data) {
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
67 uint16_t unit_size;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
68 uint32_t total_size = 0;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
69 uint8_t *out = NULL, unit_nb, sps_done = 0;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
70 const uint8_t *extradata = avctx->extradata+4;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
71 static const uint8_t nalu_header[4] = {0, 0, 0, 1};
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
72
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
73 /* retrieve length coded size */
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
74 ctx->length_size = (*extradata++ & 0x3) + 1;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
75 if (ctx->length_size == 3)
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
76 return AVERROR(EINVAL);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
77
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
78 /* retrieve sps and pps unit(s) */
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
79 unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
80 if (!unit_nb) {
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
81 unit_nb = *extradata++; /* number of pps unit(s) */
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
82 sps_done++;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
83 }
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
84 while (unit_nb--) {
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
85 unit_size = AV_RB16(extradata);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
86 total_size += unit_size+4;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
87 if (extradata+2+unit_size > avctx->extradata+avctx->extradata_size) {
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
88 av_free(out);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
89 return AVERROR(EINVAL);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
90 }
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
91 out = av_realloc(out, total_size);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
92 if (!out)
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
93 return AVERROR(ENOMEM);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
94 memcpy(out+total_size-unit_size-4, nalu_header, 4);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
95 memcpy(out+total_size-unit_size, extradata+2, unit_size);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
96 extradata += 2+unit_size;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
97
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
98 if (!unit_nb && !sps_done++)
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
99 unit_nb = *extradata++; /* number of pps unit(s) */
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
100 }
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
101
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
102 ctx->sps_pps_data = out;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
103 ctx->size = total_size;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
104 ctx->first_idr = 1;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
105 }
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
106
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
107 *poutbuf_size = 0;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
108 *poutbuf = NULL;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
109 do {
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
110 if (ctx->length_size == 1)
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
111 nal_size = buf[0];
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
112 else if (ctx->length_size == 2)
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
113 nal_size = AV_RB16(buf);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
114 else
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
115 nal_size = AV_RB32(buf);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
116
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
117 buf += ctx->length_size;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
118 unit_type = *buf & 0x1f;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
119
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
120 /* prepend only to the first type 5 NAL unit of an IDR picture */
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
121 if (ctx->first_idr && unit_type == 5) {
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
122 alloc_and_copy(poutbuf, poutbuf_size,
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
123 ctx->sps_pps_data, ctx->size,
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
124 buf, nal_size);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
125 ctx->first_idr = 0;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
126 }
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
127 else {
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
128 alloc_and_copy(poutbuf, poutbuf_size,
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
129 NULL, 0,
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
130 buf, nal_size);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
131 if (!ctx->first_idr && unit_type == 1)
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
132 ctx->first_idr = 1;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
133 }
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
134
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
135 buf += nal_size;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
136 cumul_size += nal_size + ctx->length_size;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
137 } while (cumul_size < buf_size);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
138
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
139 return 1;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
140 }
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
141
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
142 static void h264_mp4toannexb_close(AVBitStreamFilterContext *bsfc)
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
143 {
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
144 H264BSFContext *ctx = bsfc->priv_data;
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
145 av_freep(&ctx->sps_pps_data);
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
146 }
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
147
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
148 AVBitStreamFilter h264_mp4toannexb_bsf = {
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
149 "h264_mp4toannexb",
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
150 sizeof(H264BSFContext),
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
151 h264_mp4toannexb_filter,
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
152 h264_mp4toannexb_close,
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
153 };
679d6ccfffb0 Add a bitstream filter for H.264.
benoit
parents:
diff changeset
154