• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/avc.c

Go to the documentation of this file.
00001 /*
00002  * AVC helper functions for muxers
00003  * Copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@smartjog.com>
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include "libavutil/intreadwrite.h"
00023 #include "avformat.h"
00024 #include "avio.h"
00025 #include "avc.h"
00026 
00027 static const uint8_t *ff_avc_find_startcode_internal(const uint8_t *p, const uint8_t *end)
00028 {
00029     const uint8_t *a = p + 4 - ((intptr_t)p & 3);
00030 
00031     for (end -= 3; p < a && p < end; p++) {
00032         if (p[0] == 0 && p[1] == 0 && p[2] == 1)
00033             return p;
00034     }
00035 
00036     for (end -= 3; p < end; p += 4) {
00037         uint32_t x = *(const uint32_t*)p;
00038 //      if ((x - 0x01000100) & (~x) & 0x80008000) // little endian
00039 //      if ((x - 0x00010001) & (~x) & 0x00800080) // big endian
00040         if ((x - 0x01010101) & (~x) & 0x80808080) { // generic
00041             if (p[1] == 0) {
00042                 if (p[0] == 0 && p[2] == 1)
00043                     return p;
00044                 if (p[2] == 0 && p[3] == 1)
00045                     return p+1;
00046             }
00047             if (p[3] == 0) {
00048                 if (p[2] == 0 && p[4] == 1)
00049                     return p+2;
00050                 if (p[4] == 0 && p[5] == 1)
00051                     return p+3;
00052             }
00053         }
00054     }
00055 
00056     for (end += 3; p < end; p++) {
00057         if (p[0] == 0 && p[1] == 0 && p[2] == 1)
00058             return p;
00059     }
00060 
00061     return end + 3;
00062 }
00063 
00064 const uint8_t *ff_avc_find_startcode(const uint8_t *p, const uint8_t *end){
00065     const uint8_t *out= ff_avc_find_startcode_internal(p, end);
00066     if(p<out && out<end && !out[-1]) out--;
00067     return out;
00068 }
00069 
00070 int ff_avc_parse_nal_units(ByteIOContext *pb, const uint8_t *buf_in, int size)
00071 {
00072     const uint8_t *p = buf_in;
00073     const uint8_t *end = p + size;
00074     const uint8_t *nal_start, *nal_end;
00075 
00076     size = 0;
00077     nal_start = ff_avc_find_startcode(p, end);
00078     while (nal_start < end) {
00079         while(!*(nal_start++));
00080         nal_end = ff_avc_find_startcode(nal_start, end);
00081         put_be32(pb, nal_end - nal_start);
00082         put_buffer(pb, nal_start, nal_end - nal_start);
00083         size += 4 + nal_end - nal_start;
00084         nal_start = nal_end;
00085     }
00086     return size;
00087 }
00088 
00089 int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size)
00090 {
00091     ByteIOContext *pb;
00092     int ret = url_open_dyn_buf(&pb);
00093     if(ret < 0)
00094         return ret;
00095 
00096     ff_avc_parse_nal_units(pb, buf_in, *size);
00097 
00098     av_freep(buf);
00099     *size = url_close_dyn_buf(pb, buf);
00100     return 0;
00101 }
00102 
00103 int ff_isom_write_avcc(ByteIOContext *pb, const uint8_t *data, int len)
00104 {
00105     if (len > 6) {
00106         /* check for h264 start code */
00107         if (AV_RB32(data) == 0x00000001 ||
00108             AV_RB24(data) == 0x000001) {
00109             uint8_t *buf=NULL, *end, *start;
00110             uint32_t sps_size=0, pps_size=0;
00111             uint8_t *sps=0, *pps=0;
00112 
00113             int ret = ff_avc_parse_nal_units_buf(data, &buf, &len);
00114             if (ret < 0)
00115                 return ret;
00116             start = buf;
00117             end = buf + len;
00118 
00119             /* look for sps and pps */
00120             while (buf < end) {
00121                 unsigned int size;
00122                 uint8_t nal_type;
00123                 size = AV_RB32(buf);
00124                 nal_type = buf[4] & 0x1f;
00125                 if (nal_type == 7) { /* SPS */
00126                     sps = buf + 4;
00127                     sps_size = size;
00128                 } else if (nal_type == 8) { /* PPS */
00129                     pps = buf + 4;
00130                     pps_size = size;
00131                 }
00132                 buf += size + 4;
00133             }
00134             assert(sps);
00135             assert(pps);
00136 
00137             put_byte(pb, 1); /* version */
00138             put_byte(pb, sps[1]); /* profile */
00139             put_byte(pb, sps[2]); /* profile compat */
00140             put_byte(pb, sps[3]); /* level */
00141             put_byte(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */
00142             put_byte(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
00143 
00144             put_be16(pb, sps_size);
00145             put_buffer(pb, sps, sps_size);
00146             put_byte(pb, 1); /* number of pps */
00147             put_be16(pb, pps_size);
00148             put_buffer(pb, pps, pps_size);
00149             av_free(start);
00150         } else {
00151             put_buffer(pb, data, len);
00152         }
00153     }
00154     return 0;
00155 }

Generated on Fri Sep 16 2011 17:17:47 for FFmpeg by  doxygen 1.7.1