h264_mp4toannexb_bsf.c 10.2 KB
Newer Older
1
/*
2
 * H.264 MP4 to Annex B byte stream format filter
3
 * Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

22 23
#include <string.h>

24
#include "libavutil/intreadwrite.h"
25
#include "libavutil/mem.h"
26 27 28
#include "avcodec.h"

typedef struct H264BSFContext {
29 30
    int32_t  sps_offset;
    int32_t  pps_offset;
31
    uint8_t  length_size;
32
    uint8_t  new_idr;
33 34
    uint8_t  idr_sps_seen;
    uint8_t  idr_pps_seen;
35
    int      extradata_parsed;
36 37 38 39 40 41 42 43 44 45 46 47

    /* When private_spspps is zero then spspps_buf points to global extradata
       and bsf does replace a global extradata to own-allocated version (default
       behaviour).
       When private_spspps is non-zero the bsf uses a private version of spspps buf.
       This mode necessary when bsf uses in decoder, else bsf has issues after
       decoder re-initialization. Use the "private_spspps_buf" argument to
       activate this mode.
     */
    int      private_spspps;
    uint8_t *spspps_buf;
    uint32_t spspps_size;
48 49
} H264BSFContext;

50
static int alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size,
51
                          const uint8_t *sps_pps, uint32_t sps_pps_size,
52 53 54
                          const uint8_t *in, uint32_t in_size)
{
    uint32_t offset         = *poutbuf_size;
55
    uint8_t nal_header_size = offset ? 3 : 4;
56
    int err;
57

58
    *poutbuf_size += sps_pps_size + in_size + nal_header_size;
59
    if ((err = av_reallocp(poutbuf,
60
                           *poutbuf_size + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
61 62 63
        *poutbuf_size = 0;
        return err;
    }
64
    if (sps_pps)
65 66
        memcpy(*poutbuf + offset, sps_pps, sps_pps_size);
    memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size);
67
    if (!offset) {
68
        AV_WB32(*poutbuf + sps_pps_size, 1);
69
    } else {
70 71 72
        (*poutbuf + offset + sps_pps_size)[0] =
        (*poutbuf + offset + sps_pps_size)[1] = 0;
        (*poutbuf + offset + sps_pps_size)[2] = 1;
73
    }
74 75

    return 0;
76 77
}

78
static int h264_extradata_to_annexb(H264BSFContext *ctx, AVCodecContext *avctx, const int padding)
79 80 81 82 83 84 85 86 87
{
    uint16_t unit_size;
    uint64_t total_size                 = 0;
    uint8_t *out                        = NULL, unit_nb, sps_done = 0,
             sps_seen                   = 0, pps_seen = 0;
    const uint8_t *extradata            = avctx->extradata + 4;
    static const uint8_t nalu_header[4] = { 0, 0, 0, 1 };
    int length_size = (*extradata++ & 0x3) + 1; // retrieve length coded size

88 89
    ctx->sps_offset = ctx->pps_offset = -1;

90 91 92
    /* retrieve sps and pps unit(s) */
    unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */
    if (!unit_nb) {
93
        goto pps;
94
    } else {
95
        ctx->sps_offset = 0;
96 97 98 99
        sps_seen = 1;
    }

    while (unit_nb--) {
100
        int err;
101 102 103

        unit_size   = AV_RB16(extradata);
        total_size += unit_size + 4;
104 105 106 107 108 109 110 111 112
        if (total_size > INT_MAX - padding) {
            av_log(avctx, AV_LOG_ERROR,
                   "Too big extradata size, corrupted stream or invalid MP4/AVCC bitstream\n");
            av_free(out);
            return AVERROR(EINVAL);
        }
        if (extradata + 2 + unit_size > avctx->extradata + avctx->extradata_size) {
            av_log(avctx, AV_LOG_ERROR, "Packet header is not contained in global extradata, "
                   "corrupted stream or invalid MP4/AVCC bitstream\n");
113 114 115
            av_free(out);
            return AVERROR(EINVAL);
        }
116 117
        if ((err = av_reallocp(&out, total_size + padding)) < 0)
            return err;
118 119 120
        memcpy(out + total_size - unit_size - 4, nalu_header, 4);
        memcpy(out + total_size - unit_size, extradata + 2, unit_size);
        extradata += 2 + unit_size;
121
pps:
122 123
        if (!unit_nb && !sps_done++) {
            unit_nb = *extradata++; /* number of pps unit(s) */
124
            if (unit_nb) {
125
                ctx->pps_offset = total_size;
126
                pps_seen = 1;
127
            }
128 129 130 131
        }
    }

    if (out)
132
        memset(out + total_size, 0, padding);
133 134 135 136 137 138 139 140 141 142 143

    if (!sps_seen)
        av_log(avctx, AV_LOG_WARNING,
               "Warning: SPS NALU missing or invalid. "
               "The resulting stream may not play.\n");

    if (!pps_seen)
        av_log(avctx, AV_LOG_WARNING,
               "Warning: PPS NALU missing or invalid. "
               "The resulting stream may not play.\n");

144 145 146 147 148 149 150
    if (!ctx->private_spspps) {
        av_free(avctx->extradata);
        avctx->extradata      = out;
        avctx->extradata_size = total_size;
    }
    ctx->spspps_buf  = out;
    ctx->spspps_size = total_size;
151 152 153 154

    return length_size;
}

155 156
static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
                                   AVCodecContext *avctx, const char *args,
157 158 159 160
                                   uint8_t **poutbuf, int *poutbuf_size,
                                   const uint8_t *buf, int buf_size,
                                   int keyframe)
{
161
    H264BSFContext *ctx = bsfc->priv_data;
162
    int i;
163
    uint8_t unit_type;
164
    int32_t nal_size;
165
    uint32_t cumul_size    = 0;
166
    const uint8_t *buf_end = buf + buf_size;
167
    int ret = 0;
168 169 170

    /* nothing to filter */
    if (!avctx->extradata || avctx->extradata_size < 6) {
171
        *poutbuf      = (uint8_t *)buf;
172 173 174 175 176
        *poutbuf_size = buf_size;
        return 0;
    }

    /* retrieve sps and pps NAL units from extradata */
177
    if (!ctx->extradata_parsed) {
178 179 180
        if (args && strstr(args, "private_spspps_buf"))
            ctx->private_spspps = 1;

181
        ret = h264_extradata_to_annexb(ctx, avctx, AV_INPUT_BUFFER_PADDING_SIZE);
182 183 184
        if (ret < 0)
            return ret;
        ctx->length_size      = ret;
185
        ctx->new_idr          = 1;
186 187
        ctx->idr_sps_seen     = 0;
        ctx->idr_pps_seen     = 0;
188
        ctx->extradata_parsed = 1;
189 190 191
    }

    *poutbuf_size = 0;
192
    *poutbuf      = NULL;
193
    do {
194
        ret= AVERROR(EINVAL);
195 196 197
        if (buf + ctx->length_size > buf_end)
            goto fail;

198 199
        for (nal_size = 0, i = 0; i<ctx->length_size; i++)
            nal_size = (nal_size << 8) | buf[i];
200

201
        buf      += ctx->length_size;
202 203
        unit_type = *buf & 0x1f;

204
        if (nal_size > buf_end - buf || nal_size < 0)
205 206
            goto fail;

207
        if (unit_type == 7)
208
            ctx->idr_sps_seen = ctx->new_idr = 1;
209
        else if (unit_type == 8) {
210
            ctx->idr_pps_seen = ctx->new_idr = 1;
211 212 213 214 215 216
            /* if SPS has not been seen yet, prepend the AVCC one to PPS */
            if (!ctx->idr_sps_seen) {
                if (ctx->sps_offset == -1)
                    av_log(avctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n");
                else {
                    if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
217 218
                                         ctx->spspps_buf + ctx->sps_offset,
                                         ctx->pps_offset != -1 ? ctx->pps_offset : ctx->spspps_size - ctx->sps_offset,
219 220 221 222 223 224 225
                                         buf, nal_size)) < 0)
                        goto fail;
                    ctx->idr_sps_seen = 1;
                    goto next_nal;
                }
            }
        }
226

227 228 229
        /* if this is a new IDR picture following an IDR picture, reset the idr flag.
         * Just check first_mb_in_slice to be 0 as this is the simplest solution.
         * This could be checking idr_pic_id instead, but would complexify the parsing. */
230 231
        if (!ctx->new_idr && unit_type == 5 && (buf[1] & 0x80))
            ctx->new_idr = 1;
232 233

        /* prepend only to the first type 5 NAL unit of an IDR picture, if no sps/pps are already present */
234
        if (ctx->new_idr && unit_type == 5 && !ctx->idr_sps_seen && !ctx->idr_pps_seen) {
235
            if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
236
                               ctx->spspps_buf, ctx->spspps_size,
237
                               buf, nal_size)) < 0)
238
                goto fail;
239
            ctx->new_idr = 0;
240 241 242 243 244 245 246 247
        /* if only SPS has been seen, also insert PPS */
        } else if (ctx->new_idr && unit_type == 5 && ctx->idr_sps_seen && !ctx->idr_pps_seen) {
            if (ctx->pps_offset == -1) {
                av_log(avctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n");
                if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
                                     NULL, 0, buf, nal_size)) < 0)
                    goto fail;
            } else if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
248
                                        ctx->spspps_buf + ctx->pps_offset, ctx->spspps_size - ctx->pps_offset,
249 250
                                        buf, nal_size)) < 0)
                goto fail;
251
        } else {
252
            if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
253
                               NULL, 0, buf, nal_size)) < 0)
254
                goto fail;
255 256
            if (!ctx->new_idr && unit_type == 1) {
                ctx->new_idr = 1;
257 258
                ctx->idr_sps_seen = 0;
                ctx->idr_pps_seen = 0;
259
            }
260 261
        }

262
next_nal:
263
        buf        += nal_size;
264 265 266 267
        cumul_size += nal_size + ctx->length_size;
    } while (cumul_size < buf_size);

    return 1;
268 269 270 271

fail:
    av_freep(poutbuf);
    *poutbuf_size = 0;
272
    return ret;
273 274
}

275 276 277 278
static void h264_mp4toannexb_filter_close(AVBitStreamFilterContext *bsfc)
{
    H264BSFContext *ctx = bsfc->priv_data;
    if (ctx->private_spspps)
279
        av_freep(&ctx->spspps_buf);
280 281
}

282
AVBitStreamFilter ff_h264_mp4toannexb_bsf = {
283 284 285
    .name           = "h264_mp4toannexb",
    .priv_data_size = sizeof(H264BSFContext),
    .filter         = h264_mp4toannexb_filter,
286
    .close          = h264_mp4toannexb_filter_close,
287
};