PageRenderTime 52ms CodeModel.GetById 2ms app.highlight 45ms RepoModel.GetById 1ms app.codeStats 0ms

/src/avc.c

https://code.google.com/
C | 298 lines | 197 code | 28 blank | 73 comment | 63 complexity | aa737072c29cc1a0f38382dfff658dac MD5 | raw file
  1/*
  2    $Id: avc.c 231 2011-06-27 13:46:19Z marc.noirot $
  3
  4    FLV Metadata updater
  5
  6    Copyright (C) 2007-2012 Marc Noirot <marc.noirot AT gmail.com>
  7
  8    This file is part of FLVMeta.
  9
 10    FLVMeta is free software; you can redistribute it and/or modify
 11    it under the terms of the GNU General Public License as published by
 12    the Free Software Foundation; either version 2 of the License, or
 13    (at your option) any later version.
 14
 15    FLVMeta is distributed in the hope that it will be useful,
 16    but WITHOUT ANY WARRANTY; without even the implied warranty of
 17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18    GNU General Public License for more details.
 19
 20    You should have received a copy of the GNU General Public License
 21    along with FLVMeta; if not, write to the Free Software
 22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 23*/
 24#include <stdlib.h>
 25
 26#include "avc.h"
 27
 28/**
 29    bit buffer handling
 30*/
 31typedef struct __bit_buffer {
 32    byte * start;
 33    /*size_t size;*/
 34    byte * current;
 35    uint8 read_bits;
 36} bit_buffer;
 37
 38static void skip_bits(bit_buffer * bb, size_t nbits) {
 39    bb->current = bb->current + ((nbits + bb->read_bits) / 8);
 40    bb->read_bits = (uint8)((bb->read_bits + nbits) % 8);
 41}
 42
 43static uint8 get_bit(bit_buffer * bb) {
 44    uint8 ret;
 45    ret = (*(bb->current) >> (7 - bb->read_bits)) & 0x1;
 46    if (bb->read_bits == 7) {
 47        bb->read_bits = 0;
 48        bb->current++;
 49    }
 50    else {
 51        bb->read_bits++;
 52    }
 53    return ret;
 54}
 55
 56static uint32 get_bits(bit_buffer * bb, size_t nbits) {
 57    uint32 i, ret;
 58    ret = 0;
 59    for (i = 0; i < nbits; i++) {
 60        ret = (ret << 1) + get_bit(bb);
 61    }
 62    return ret;
 63}
 64
 65static uint32 exp_golomb_ue(bit_buffer * bb) {
 66    uint8 bit, significant_bits;
 67    significant_bits = 0;
 68    bit = get_bit(bb);
 69    while (bit == 0) {
 70        significant_bits++;
 71        bit = get_bit(bb);
 72    }
 73    return (1 << significant_bits) + get_bits(bb, significant_bits) - 1;
 74}
 75
 76static sint32 exp_golomb_se(bit_buffer * bb) {
 77    sint32 ret;
 78    ret = exp_golomb_ue(bb);
 79    if ((ret & 0x1) == 0) {
 80        return -(ret >> 1);
 81    }
 82    else {
 83        return (ret + 1) >> 1;
 84    }
 85}
 86
 87/* AVC type definitions */
 88
 89#define AVC_SEQUENCE_HEADER 0
 90#define AVC_NALU            1
 91#define AVC_END_OF_SEQUENCE 2
 92
 93typedef struct __AVCDecoderConfigurationRecord {
 94    uint8 configurationVersion;
 95    uint8 AVCProfileIndication;
 96    uint8 profile_compatibility;
 97    uint8 AVCLevelIndication;
 98    uint8 lengthSizeMinusOne;
 99    uint8 numOfSequenceParameterSets;
100} AVCDecoderConfigurationRecord;
101
102int read_avc_decoder_configuration_record(flv_stream * f, AVCDecoderConfigurationRecord * adcr) {
103    if (flv_read_tag_body(f, &adcr->configurationVersion, 1) == 1
104    && flv_read_tag_body(f, &adcr->AVCProfileIndication, 1) == 1
105    && flv_read_tag_body(f, &adcr->profile_compatibility, 1) == 1
106    && flv_read_tag_body(f, &adcr->AVCLevelIndication, 1) == 1
107    && flv_read_tag_body(f, &adcr->lengthSizeMinusOne, 1) == 1
108    && flv_read_tag_body(f, &adcr->numOfSequenceParameterSets, 1) == 1) {
109        return FLV_OK;
110    }
111    else {
112        return FLV_ERROR_EOF;
113    }
114}
115
116
117static void parse_scaling_list(uint32 size, bit_buffer * bb) {
118    uint32 last_scale, next_scale, i;
119    sint32 delta_scale;
120    last_scale = 8;
121    next_scale = 8;
122    for (i = 0; i < size; i++) {
123        if (next_scale != 0) {
124            delta_scale = exp_golomb_se(bb);
125            next_scale = (last_scale + delta_scale + 256) % 256;
126        }
127        if (next_scale != 0) {
128            last_scale = next_scale;
129        }
130    }
131}
132
133/**
134    Parses a SPS NALU to retrieve video width and height
135*/
136static void parse_sps(byte * sps, size_t sps_size, uint32 * width, uint32 * height) {
137    bit_buffer bb;
138    uint32 profile, pic_order_cnt_type, width_in_mbs, height_in_map_units;
139    uint32 i, size, left, right, top, bottom;
140    uint8 frame_mbs_only_flag;
141
142    bb.start = sps;
143    /*bb.size = sps_size;*/
144    bb.current = sps;
145    bb.read_bits = 0;
146
147    /* skip first byte, since we already know we're parsing a SPS */
148    skip_bits(&bb, 8);
149    /* get profile */
150    profile = get_bits(&bb, 8);
151    /* skip 4 bits + 4 zeroed bits + 8 bits = 16 bits = 2 bytes */
152    skip_bits(&bb, 16);
153
154    /* read sps id, first exp-golomb encoded value */
155    exp_golomb_ue(&bb);
156
157    if (profile == 100 || profile == 110 || profile == 122 || profile == 144) {
158        /* chroma format idx */
159        if (exp_golomb_ue(&bb) == 3) {
160            skip_bits(&bb, 1);
161        }
162        /* bit depth luma minus8 */
163        exp_golomb_ue(&bb);
164        /* bit depth chroma minus8 */
165        exp_golomb_ue(&bb);
166        /* Qpprime Y Zero Transform Bypass flag */
167        skip_bits(&bb, 1);
168        /* Seq Scaling Matrix Present Flag */
169        if (get_bit(&bb)) {
170            for (i = 0; i < 8; i++) {
171                /* Seq Scaling List Present Flag */
172                if (get_bit(&bb)) {
173                    parse_scaling_list(i < 6 ? 16 : 64, &bb);
174                }
175            }
176        }
177    }
178    /* log2_max_frame_num_minus4 */
179    exp_golomb_ue(&bb);
180    /* pic_order_cnt_type */
181    pic_order_cnt_type = exp_golomb_ue(&bb);
182    if (pic_order_cnt_type == 0) {
183        /* log2_max_pic_order_cnt_lsb_minus4 */
184        exp_golomb_ue(&bb);
185    }
186    else if (pic_order_cnt_type == 1) {
187        /* delta_pic_order_always_zero_flag */
188        skip_bits(&bb, 1);
189        /* offset_for_non_ref_pic */
190        exp_golomb_se(&bb);
191        /* offset_for_top_to_bottom_field */
192        exp_golomb_se(&bb);
193        size = exp_golomb_ue(&bb);
194        for (i = 0; i < size; i++) {
195            /* offset_for_ref_frame */
196            exp_golomb_se(&bb);
197        }
198    }
199    /* num_ref_frames */
200    exp_golomb_ue(&bb);
201    /* gaps_in_frame_num_value_allowed_flag */
202    skip_bits(&bb, 1);
203    /* pic_width_in_mbs */
204    width_in_mbs = exp_golomb_ue(&bb) + 1;
205    /* pic_height_in_map_units */
206    height_in_map_units = exp_golomb_ue(&bb) + 1;
207    /* frame_mbs_only_flag */
208    frame_mbs_only_flag = get_bit(&bb);
209    if (!frame_mbs_only_flag) {
210        /* mb_adaptive_frame_field */
211        skip_bits(&bb, 1);
212    }
213    /* direct_8x8_inference_flag */
214    skip_bits(&bb, 1);
215    /* frame_cropping */
216    left = right = top = bottom = 0;
217    if (get_bit(&bb)) {
218        left = exp_golomb_ue(&bb) * 2;
219        right = exp_golomb_ue(&bb) * 2;
220        top = exp_golomb_ue(&bb) * 2;
221        bottom = exp_golomb_ue(&bb) * 2;
222        if (!frame_mbs_only_flag) {
223            top *= 2;
224            bottom *= 2;
225        }
226    }
227    /* width */
228    *width = width_in_mbs * 16 - (left + right);
229    /* height */
230    *height = height_in_map_units * 16 - (top + bottom);
231    if (!frame_mbs_only_flag) {
232        *height *= 2;
233    }
234}
235
236/**
237    Tries to read the resolution of the current video packet.
238    We assume to be at the first byte of the video data.
239*/
240int read_avc_resolution(flv_stream * f, uint32 body_length, uint32 * width, uint32 * height) {
241    byte avc_packet_type;
242    uint24 composition_time;
243    AVCDecoderConfigurationRecord adcr;
244    uint16 sps_size;
245    byte * sps_buffer;
246
247    /* make sure we have enough bytes to read in the current tag */
248    if (body_length < sizeof(byte) + sizeof(uint24) + sizeof(AVCDecoderConfigurationRecord)) {
249        return FLV_OK;
250    }
251
252    /* determine whether we're reading an AVCDecoderConfigurationRecord */
253    if (flv_read_tag_body(f, &avc_packet_type, 1) < 1) {
254        return FLV_ERROR_EOF;
255    }
256    if (avc_packet_type != AVC_SEQUENCE_HEADER) {
257        return FLV_OK;
258    }
259
260    /* read the composition time */
261    if (flv_read_tag_body(f, &composition_time, sizeof(uint24)) < sizeof(uint24)) {
262        return FLV_ERROR_EOF;
263    }
264
265    /* we need to read an AVCDecoderConfigurationRecord */
266    if (read_avc_decoder_configuration_record(f, &adcr) == FLV_ERROR_EOF) {
267        return FLV_ERROR_EOF;
268    }
269
270    /* number of SequenceParameterSets */
271    if ((adcr.numOfSequenceParameterSets & 0x1F) == 0) {
272        /* no SPS, return */
273        return FLV_OK;
274    }
275
276    /** read the first SequenceParameterSet found */
277    /* SPS size */
278    if (flv_read_tag_body(f, &sps_size, sizeof(uint16)) < sizeof(uint16)) {
279        return FLV_ERROR_EOF;
280    }
281    sps_size = swap_uint16(sps_size);
282    
283    /* read the SPS entirely */
284    sps_buffer = (byte *) malloc((size_t)sps_size);
285    if (sps_buffer == NULL) {
286        return FLV_ERROR_MEMORY;
287    }
288    if (flv_read_tag_body(f, sps_buffer, (size_t)sps_size) < (size_t)sps_size) {
289        free(sps_buffer);
290        return FLV_ERROR_EOF;
291    }
292
293    /* parse SPS to determine video resolution */
294    parse_sps(sps_buffer, (size_t)sps_size, width, height);
295    
296    free(sps_buffer);
297    return FLV_OK;
298}