1/* 2 * H.264 MP4 to Annex B byte stream format filter 3 * Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr> 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 22#include "libavutil/intreadwrite.h" 23#include "avcodec.h" 24 25typedef struct H264BSFContext { 26 uint8_t length_size; 27 uint8_t first_idr; 28 uint8_t *sps_pps_data; 29 uint32_t size; 30} H264BSFContext; 31 32static void alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size, 33 const uint8_t *sps_pps, uint32_t sps_pps_size, 34 const uint8_t *in, uint32_t in_size) { 35 uint32_t offset = *poutbuf_size; 36 uint8_t nal_header_size = offset ? 3 : 4; 37 38 *poutbuf_size += sps_pps_size+in_size+nal_header_size; 39 *poutbuf = av_realloc(*poutbuf, *poutbuf_size); 40 if (sps_pps) 41 memcpy(*poutbuf+offset, sps_pps, sps_pps_size); 42 memcpy(*poutbuf+sps_pps_size+nal_header_size+offset, in, in_size); 43 if (!offset) 44 AV_WB32(*poutbuf+sps_pps_size, 1); 45 else { 46 (*poutbuf+offset+sps_pps_size)[0] = (*poutbuf+offset+sps_pps_size)[1] = 0; 47 (*poutbuf+offset+sps_pps_size)[2] = 1; 48 } 49} 50 51static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc, 52 AVCodecContext *avctx, const char *args, 53 uint8_t **poutbuf, int *poutbuf_size, 54 const uint8_t *buf, int buf_size, 55 int keyframe) { 56 H264BSFContext *ctx = bsfc->priv_data; 57 uint8_t unit_type; 58 int32_t nal_size; 59 uint32_t cumul_size = 0; 60 const uint8_t *buf_end = buf + buf_size; 61 62 /* nothing to filter */ 63 if (!avctx->extradata || avctx->extradata_size < 6) { 64 *poutbuf = (uint8_t*) buf; 65 *poutbuf_size = buf_size; 66 return 0; 67 } 68 69 /* retrieve sps and pps NAL units from extradata */ 70 if (!ctx->sps_pps_data) { 71 uint16_t unit_size; 72 uint32_t total_size = 0; 73 uint8_t *out = NULL, unit_nb, sps_done = 0; 74 const uint8_t *extradata = avctx->extradata+4; 75 static const uint8_t nalu_header[4] = {0, 0, 0, 1}; 76 77 /* retrieve length coded size */ 78 ctx->length_size = (*extradata++ & 0x3) + 1; 79 if (ctx->length_size == 3) 80 return AVERROR(EINVAL); 81 82 /* retrieve sps and pps unit(s) */ 83 unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */ 84 if (!unit_nb) { 85 unit_nb = *extradata++; /* number of pps unit(s) */ 86 sps_done++; 87 } 88 while (unit_nb--) { 89 unit_size = AV_RB16(extradata); 90 total_size += unit_size+4; 91 if (extradata+2+unit_size > avctx->extradata+avctx->extradata_size) { 92 av_free(out); 93 return AVERROR(EINVAL); 94 } 95 out = av_realloc(out, total_size); 96 if (!out) 97 return AVERROR(ENOMEM); 98 memcpy(out+total_size-unit_size-4, nalu_header, 4); 99 memcpy(out+total_size-unit_size, extradata+2, unit_size); 100 extradata += 2+unit_size; 101 102 if (!unit_nb && !sps_done++) 103 unit_nb = *extradata++; /* number of pps unit(s) */ 104 } 105 106 ctx->sps_pps_data = out; 107 ctx->size = total_size; 108 ctx->first_idr = 1; 109 } 110 111 *poutbuf_size = 0; 112 *poutbuf = NULL; 113 do { 114 if (buf + ctx->length_size > buf_end) 115 goto fail; 116 117 if (ctx->length_size == 1) 118 nal_size = buf[0]; 119 else if (ctx->length_size == 2) 120 nal_size = AV_RB16(buf); 121 else 122 nal_size = AV_RB32(buf); 123 124 buf += ctx->length_size; 125 unit_type = *buf & 0x1f; 126 127 if (buf + nal_size > buf_end || nal_size < 0) 128 goto fail; 129 130 /* prepend only to the first type 5 NAL unit of an IDR picture */ 131 if (ctx->first_idr && unit_type == 5) { 132 alloc_and_copy(poutbuf, poutbuf_size, 133 ctx->sps_pps_data, ctx->size, 134 buf, nal_size); 135 ctx->first_idr = 0; 136 } 137 else { 138 alloc_and_copy(poutbuf, poutbuf_size, 139 NULL, 0, 140 buf, nal_size); 141 if (!ctx->first_idr && unit_type == 1) 142 ctx->first_idr = 1; 143 } 144 145 buf += nal_size; 146 cumul_size += nal_size + ctx->length_size; 147 } while (cumul_size < buf_size); 148 149 return 1; 150 151fail: 152 av_freep(poutbuf); 153 *poutbuf_size = 0; 154 return AVERROR(EINVAL); 155} 156 157static void h264_mp4toannexb_close(AVBitStreamFilterContext *bsfc) 158{ 159 H264BSFContext *ctx = bsfc->priv_data; 160 av_freep(&ctx->sps_pps_data); 161} 162 163AVBitStreamFilter h264_mp4toannexb_bsf = { 164 "h264_mp4toannexb", 165 sizeof(H264BSFContext), 166 h264_mp4toannexb_filter, 167 h264_mp4toannexb_close, 168}; 169 170