⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 header.c

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * header.c
 * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
 * Copyright (C) 2003      Regis Duchesne <hpreg@zoy.org>
 * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
 *
 * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
 * See http://libmpeg2.sourceforge.net/ for updates.
 *
 * mpeg2dec is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * mpeg2dec 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */


#include <stdlib.h>	/* defines NULL */
#include <string.h>	/* memcmp */
#include <inttypes.h>

#include "config.h"
#include "mpeg2.h"
#include "attributes.h"
#include "mpeg2_internal.h"

#define SEQ_EXT 2
#define SEQ_DISPLAY_EXT 4
#define QUANT_MATRIX_EXT 8
#define COPYRIGHT_EXT 0x10
#define PIC_DISPLAY_EXT 0x80
#define PIC_CODING_EXT 0x100

/* default intra quant matrix, in zig-zag order */
static __align16(const uint8_t,default_intra_quantizer_matrix[64]) = {
    8,
    16, 16,
    19, 16, 19,
    22, 22, 22, 22,
    22, 22, 26, 24, 26,
    27, 27, 27, 26, 26, 26,
    26, 27, 27, 27, 29, 29, 29,
    34, 34, 34, 29, 29, 29, 27, 27,
    29, 29, 32, 32, 34, 34, 37,
    38, 37, 35, 35, 34, 35,
    38, 38, 40, 40, 40,
    48, 48, 46, 46,
    56, 56, 58,
    69, 69,
    83
};

__align16(uint8_t,mpeg2_scan_norm[64]) = {
    /* Zig-Zag scan pattern */
     0,  1,  8, 16,  9,  2,  3, 10, 17, 24, 32, 25, 18, 11,  4,  5,
    12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13,  6,  7, 14, 21, 28,
    35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
    58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
};

__align16(uint8_t,mpeg2_scan_alt[64]) = {
    /* Alternate scan pattern */
     0, 8,  16, 24,  1,  9,  2, 10, 17, 25, 32, 40, 48, 56, 57, 49,
    41, 33, 26, 18,  3, 11,  4, 12, 19, 27, 34, 42, 50, 58, 35, 43,
    51, 59, 20, 28,  5, 13,  6, 14, 21, 29, 36, 44, 52, 60, 37, 45,
    53, 61, 22, 30,  7, 15, 23, 31, 38, 46, 54, 62, 39, 47, 55, 63
};

void mpeg2_header_state_init (mpeg2dec_t * mpeg2dec)
{
    if (mpeg2dec->sequence.width != (unsigned)-1) {
	int i;

	mpeg2dec->sequence.width = (unsigned)-1;
	if (!mpeg2dec->custom_fbuf)
	    for (i = mpeg2dec->alloc_index_user;
		 i < mpeg2dec->alloc_index; i++) {
		mpeg2_free (mpeg2dec->fbuf_alloc[i].fbuf.buf[0]);
		mpeg2_free (mpeg2dec->fbuf_alloc[i].fbuf.buf[1]);
		mpeg2_free (mpeg2dec->fbuf_alloc[i].fbuf.buf[2]);
	    }
	if (mpeg2dec->convert_start)
	    for (i = 0; i < 3; i++) {
		mpeg2_free (mpeg2dec->yuv_buf[i][0]);
		mpeg2_free (mpeg2dec->yuv_buf[i][1]);
		mpeg2_free (mpeg2dec->yuv_buf[i][2]);
    }
	if (mpeg2dec->decoder.convert_id)
	    mpeg2_free (mpeg2dec->decoder.convert_id);
    }
    mpeg2dec->decoder.coding_type = I_TYPE;
    mpeg2dec->decoder.convert = NULL;
    mpeg2dec->decoder.convert_id = NULL;
    mpeg2dec->picture = mpeg2dec->pictures;
    mpeg2dec->fbuf[0] = &mpeg2dec->fbuf_alloc[0].fbuf;
    mpeg2dec->fbuf[1] = &mpeg2dec->fbuf_alloc[1].fbuf;
    mpeg2dec->fbuf[2] = &mpeg2dec->fbuf_alloc[2].fbuf;
    mpeg2dec->first = 1;
    mpeg2dec->alloc_index = 0;
    mpeg2dec->alloc_index_user = 0;
    mpeg2dec->first_decode_slice = 1;
    mpeg2dec->nb_decode_slices = 0xb0 - 1;
    mpeg2dec->convert = NULL;
    mpeg2dec->convert_start = NULL;
    mpeg2dec->custom_fbuf = 0;
    mpeg2dec->yuv_index = 0;
}

void mpeg2_reset_info (mpeg2_info_t * info)
{
    info->current_picture = info->current_picture_2nd = NULL;
    info->display_picture = info->display_picture_2nd = NULL;
    info->current_fbuf = info->display_fbuf = info->discard_fbuf = NULL;
}

static void info_user_data (mpeg2dec_t * mpeg2dec)
{
    if (mpeg2dec->user_data_len) {
	mpeg2dec->info.user_data = mpeg2dec->chunk_buffer;
	mpeg2dec->info.user_data_len = mpeg2dec->user_data_len - 3;
    }
}

int mpeg2_header_sequence (mpeg2dec_t * mpeg2dec)
{
    uint8_t * buffer = mpeg2dec->chunk_start;
    mpeg2_sequence_t * sequence = &(mpeg2dec->new_sequence);
    static unsigned int frame_period[16] = {
	0, 1126125, 1125000, 1080000, 900900, 900000, 540000, 450450, 450000,
	/* unofficial: xing 15 fps */
	1800000,
	/* unofficial: libmpeg3 "Unofficial economy rates" 5/10/12/15 fps */
	5400000, 2700000, 2250000, 1800000, 0, 0
    };
    int i;

    if ((buffer[6] & 0x20) != 0x20)	/* missing marker_bit */
	return 1;

    i = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
    if (! (sequence->display_width = sequence->picture_width = i >> 12))
	return 1;
    if (! (sequence->display_height = sequence->picture_height = i & 0xfff))
	return 1;
    sequence->width = (sequence->picture_width + 15) & ~15;
    sequence->height = (sequence->picture_height + 15) & ~15;
    sequence->chroma_width = sequence->width >> 1;
    sequence->chroma_height = sequence->height >> 1;

    sequence->flags = (SEQ_FLAG_PROGRESSIVE_SEQUENCE |
		       SEQ_VIDEO_FORMAT_UNSPECIFIED);

    sequence->pixel_width = buffer[3] >> 4;	/* aspect ratio */
	sequence->frame_period = frame_period[buffer[3] & 15];

    sequence->byte_rate = (buffer[4]<<10) | (buffer[5]<<2) | (buffer[6]>>6);

    sequence->vbv_buffer_size = ((buffer[6]<<16)|(buffer[7]<<8))&0x1ff800;

    if (buffer[7] & 4)
	sequence->flags |= SEQ_FLAG_CONSTRAINED_PARAMETERS;

    mpeg2dec->copy_matrix = 3;
    if (buffer[7] & 2) {
	for (i = 0; i < 64; i++)
	    mpeg2dec->new_quantizer_matrix[0][mpeg2_scan_norm[i]] =
		(buffer[i+7] << 7) | (buffer[i+8] >> 1);
	buffer += 64;
    } else
	for (i = 0; i < 64; i++)
	    mpeg2dec->new_quantizer_matrix[0][mpeg2_scan_norm[i]] =
		default_intra_quantizer_matrix [i];

    if (buffer[7] & 1)
	for (i = 0; i < 64; i++)
	    mpeg2dec->new_quantizer_matrix[1][mpeg2_scan_norm[i]] =
		buffer[i+8];
    else
	memset (mpeg2dec->new_quantizer_matrix[1], 16, 64);

    sequence->profile_level_id = 0x80;
    sequence->colour_primaries = 0;
    sequence->transfer_characteristics = 0;
    sequence->matrix_coefficients = 0;

    mpeg2dec->ext_state = SEQ_EXT;
    mpeg2dec->state = STATE_SEQUENCE;
    mpeg2dec->display_offset_x = mpeg2dec->display_offset_y = 0;

    return 0;
}

static int sequence_ext (mpeg2dec_t * mpeg2dec)
{
    uint8_t * buffer = mpeg2dec->chunk_start;
    mpeg2_sequence_t * sequence = &(mpeg2dec->new_sequence);
    uint32_t flags;

    if (!(buffer[3] & 1))
	return 1;

    sequence->profile_level_id = (buffer[0] << 4) | (buffer[1] >> 4);

    sequence->display_width = sequence->picture_width +=
	((buffer[1] << 13) | (buffer[2] << 5)) & 0x3000;
    sequence->display_height = sequence->picture_height +=
	(buffer[2] << 7) & 0x3000;
    sequence->width = (sequence->picture_width + 15) & ~15;
    sequence->height = (sequence->picture_height + 15) & ~15;
    flags = sequence->flags | SEQ_FLAG_MPEG2;
    if (!(buffer[1] & 8)) {
	flags &= ~SEQ_FLAG_PROGRESSIVE_SEQUENCE;
	sequence->height = (sequence->height + 31) & ~31;
    }
    if (buffer[5] & 0x80)
	flags |= SEQ_FLAG_LOW_DELAY;
    sequence->flags = flags;
    sequence->chroma_width = sequence->width;
    sequence->chroma_height = sequence->height;
    switch (buffer[1] & 6) {
    case 0:	/* invalid */
	return 1;
    case 2:	/* 4:2:0 */
	sequence->chroma_height >>= 1;
    case 4:	/* 4:2:2 */
	sequence->chroma_width >>= 1;
    }

    sequence->byte_rate += ((buffer[2]<<25) | (buffer[3]<<17)) & 0x3ffc0000;

    sequence->vbv_buffer_size |= buffer[4] << 21;

    sequence->frame_period =
	sequence->frame_period * ((buffer[5]&31)+1) / (((buffer[5]>>2)&3)+1);

    mpeg2dec->ext_state = SEQ_DISPLAY_EXT;

    return 0;
}

static int sequence_display_ext (mpeg2dec_t * mpeg2dec)
{
    uint8_t * buffer = mpeg2dec->chunk_start;
    mpeg2_sequence_t * sequence = &(mpeg2dec->new_sequence);

    sequence->flags = ((sequence->flags & ~SEQ_MASK_VIDEO_FORMAT) |
	     ((buffer[0]<<4) & SEQ_MASK_VIDEO_FORMAT));
    if (buffer[0] & 1) {
	sequence->flags |= SEQ_FLAG_COLOUR_DESCRIPTION;
	sequence->colour_primaries = buffer[1];
	sequence->transfer_characteristics = buffer[2];
	sequence->matrix_coefficients = buffer[3];
	buffer += 3;
    }

    if (!(buffer[2] & 2))	/* missing marker_bit */
	return 1;

    if( (buffer[1] << 6) | (buffer[2] >> 2) )
    sequence->display_width = (buffer[1] << 6) | (buffer[2] >> 2);
    if( ((buffer[2]& 1 ) << 13) | (buffer[3] << 5) | (buffer[4] >> 3) )
    sequence->display_height =
	((buffer[2]& 1 ) << 13) | (buffer[3] << 5) | (buffer[4] >> 3);

    return 0;
}

static inline void simplify (unsigned int * u, unsigned int * v)
{
    unsigned int a, b, tmp;

    a = *u;	b = *v;
    while (a) {	/* find greatest common divisor */
	tmp = a;	a = b % tmp;	b = tmp;
    }
    *u /= b;	*v /= b;
}

static inline void finalize_sequence (mpeg2_sequence_t * sequence)
{
    int width;
    int height;

    sequence->byte_rate *= 50;

    if (sequence->flags & SEQ_FLAG_MPEG2) {
	switch (sequence->pixel_width) {
	case 1:		/* square pixels */
	    sequence->pixel_width = sequence->pixel_height = 1;	return;
	case 2:		/* 4:3 aspect ratio */
	    width = 4; height = 3;	break;
	case 3:		/* 16:9 aspect ratio */
	    width = 16; height = 9;	break;
	case 4:		/* 2.21:1 aspect ratio */
	    width = 221; height = 100;	break;
	default:	/* illegal */
	    sequence->pixel_width = sequence->pixel_height = 0;	return;
	}
	width *= sequence->display_height;
	height *= sequence->display_width;

    } else {
	if (sequence->byte_rate == 50 * 0x3ffff)
	    sequence->byte_rate = 0;        /* mpeg-1 VBR */

	switch (sequence->pixel_width) {
	case 0:	case 15:	/* illegal */
	    sequence->pixel_width = sequence->pixel_height = 0;		return;
	case 1:	/* square pixels */
	    sequence->pixel_width = sequence->pixel_height = 1;		return;
	case 3:	/* 720x576 16:9 */
	    sequence->pixel_width = 64;	sequence->pixel_height = 45;	return;
	case 6:	/* 720x480 16:9 */
	    sequence->pixel_width = 32;	sequence->pixel_height = 27;	return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -