yading@11: /* yading@11: * AVC helper functions for muxers yading@11: * Copyright (c) 2006 Baptiste Coudurier yading@11: * yading@11: * This file is part of FFmpeg. yading@11: * yading@11: * FFmpeg is free software; you can redistribute it and/or yading@11: * modify it under the terms of the GNU Lesser General Public yading@11: * License as published by the Free Software Foundation; either yading@11: * version 2.1 of the License, or (at your option) any later version. yading@11: * yading@11: * FFmpeg is distributed in the hope that it will be useful, yading@11: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@11: * Lesser General Public License for more details. yading@11: * yading@11: * You should have received a copy of the GNU Lesser General Public yading@11: * License along with FFmpeg; if not, write to the Free Software yading@11: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@11: */ yading@11: yading@11: #include "libavutil/intreadwrite.h" yading@11: #include "avformat.h" yading@11: #include "avio.h" yading@11: #include "avc.h" yading@11: yading@11: static const uint8_t *ff_avc_find_startcode_internal(const uint8_t *p, const uint8_t *end) yading@11: { yading@11: const uint8_t *a = p + 4 - ((intptr_t)p & 3); yading@11: yading@11: for (end -= 3; p < a && p < end; p++) { yading@11: if (p[0] == 0 && p[1] == 0 && p[2] == 1) yading@11: return p; yading@11: } yading@11: yading@11: for (end -= 3; p < end; p += 4) { yading@11: uint32_t x = *(const uint32_t*)p; yading@11: // if ((x - 0x01000100) & (~x) & 0x80008000) // little endian yading@11: // if ((x - 0x00010001) & (~x) & 0x00800080) // big endian yading@11: if ((x - 0x01010101) & (~x) & 0x80808080) { // generic yading@11: if (p[1] == 0) { yading@11: if (p[0] == 0 && p[2] == 1) yading@11: return p; yading@11: if (p[2] == 0 && p[3] == 1) yading@11: return p+1; yading@11: } yading@11: if (p[3] == 0) { yading@11: if (p[2] == 0 && p[4] == 1) yading@11: return p+2; yading@11: if (p[4] == 0 && p[5] == 1) yading@11: return p+3; yading@11: } yading@11: } yading@11: } yading@11: yading@11: for (end += 3; p < end; p++) { yading@11: if (p[0] == 0 && p[1] == 0 && p[2] == 1) yading@11: return p; yading@11: } yading@11: yading@11: return end + 3; yading@11: } yading@11: yading@11: const uint8_t *ff_avc_find_startcode(const uint8_t *p, const uint8_t *end){ yading@11: const uint8_t *out= ff_avc_find_startcode_internal(p, end); yading@11: if(p 6) { yading@11: /* check for h264 start code */ yading@11: if (AV_RB32(data) == 0x00000001 || yading@11: AV_RB24(data) == 0x000001) { yading@11: uint8_t *buf=NULL, *end, *start; yading@11: uint32_t sps_size=0, pps_size=0; yading@11: uint8_t *sps=0, *pps=0; yading@11: yading@11: int ret = ff_avc_parse_nal_units_buf(data, &buf, &len); yading@11: if (ret < 0) yading@11: return ret; yading@11: start = buf; yading@11: end = buf + len; yading@11: yading@11: /* look for sps and pps */ yading@11: while (end - buf > 4) { yading@11: uint32_t size; yading@11: uint8_t nal_type; yading@11: size = FFMIN(AV_RB32(buf), end - buf - 4); yading@11: buf += 4; yading@11: nal_type = buf[0] & 0x1f; yading@11: yading@11: if (nal_type == 7) { /* SPS */ yading@11: sps = buf; yading@11: sps_size = size; yading@11: } else if (nal_type == 8) { /* PPS */ yading@11: pps = buf; yading@11: pps_size = size; yading@11: } yading@11: yading@11: buf += size; yading@11: } yading@11: yading@11: if (!sps || !pps || sps_size < 4 || sps_size > UINT16_MAX || pps_size > UINT16_MAX) yading@11: return AVERROR_INVALIDDATA; yading@11: yading@11: avio_w8(pb, 1); /* version */ yading@11: avio_w8(pb, sps[1]); /* profile */ yading@11: avio_w8(pb, sps[2]); /* profile compat */ yading@11: avio_w8(pb, sps[3]); /* level */ yading@11: avio_w8(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */ yading@11: avio_w8(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */ yading@11: yading@11: avio_wb16(pb, sps_size); yading@11: avio_write(pb, sps, sps_size); yading@11: avio_w8(pb, 1); /* number of pps */ yading@11: avio_wb16(pb, pps_size); yading@11: avio_write(pb, pps, pps_size); yading@11: av_free(start); yading@11: } else { yading@11: avio_write(pb, data, len); yading@11: } yading@11: } yading@11: return 0; yading@11: } yading@11: yading@11: int ff_avc_write_annexb_extradata(const uint8_t *in, uint8_t **buf, int *size) yading@11: { yading@11: uint16_t sps_size, pps_size; yading@11: uint8_t *out; yading@11: int out_size; yading@11: yading@11: *buf = NULL; yading@11: if (*size >= 4 && (AV_RB32(in) == 0x00000001 || AV_RB24(in) == 0x000001)) yading@11: return 0; yading@11: if (*size < 11 || in[0] != 1) yading@11: return AVERROR_INVALIDDATA; yading@11: yading@11: sps_size = AV_RB16(&in[6]); yading@11: if (11 + sps_size > *size) yading@11: return AVERROR_INVALIDDATA; yading@11: pps_size = AV_RB16(&in[9 + sps_size]); yading@11: if (11 + sps_size + pps_size > *size) yading@11: return AVERROR_INVALIDDATA; yading@11: out_size = 8 + sps_size + pps_size; yading@11: out = av_mallocz(out_size); yading@11: if (!out) yading@11: return AVERROR(ENOMEM); yading@11: AV_WB32(&out[0], 0x00000001); yading@11: memcpy(out + 4, &in[8], sps_size); yading@11: AV_WB32(&out[4 + sps_size], 0x00000001); yading@11: memcpy(out + 8 + sps_size, &in[11 + sps_size], pps_size); yading@11: *buf = out; yading@11: *size = out_size; yading@11: return 0; yading@11: }