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

📄 mpegvideo.c

📁 杜比AC-3编码解码器(参考程序)
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * The simplest mpeg encoder
 * Copyright (c) 2000 Gerard Lantau.
 *
 * This program 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.
 *
 * This program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#include <stdlib.h>
#include <stdio.h>
#include <netinet/in.h>
#include <math.h>
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"

/* enable all paranoid tests for rounding, overflows, etc... */
//#define PARANOID

//#define DEBUG

/* for jpeg fast DCT */
#define CONST_BITS 14

static const unsigned short aanscales[64] = {
    /* precomputed values scaled up by 14 bits */
    16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
    22725, 31521, 29692, 26722, 22725, 17855, 12299,  6270,
    21407, 29692, 27969, 25172, 21407, 16819, 11585,  5906,
    19266, 26722, 25172, 22654, 19266, 15137, 10426,  5315,
    16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
    12873, 17855, 16819, 15137, 12873, 10114,  6967,  3552,
    8867, 12299, 11585, 10426,  8867,  6967,  4799,  2446,
    4520,  6270,  5906,  5315,  4520,  3552,  2446,  1247
};

static void encode_picture(MpegEncContext *s, int picture_number);
static void rate_control_init(MpegEncContext *s);
static int rate_estimate_qscale(MpegEncContext *s);
static void mpeg1_skip_picture(MpegEncContext *s, int pict_num);

#include "mpegencodevlc.h"

static void put_header(MpegEncContext *s, int header)
{
    align_put_bits(&s->pb);
    put_bits(&s->pb, 32, header);
}

static void convert_matrix(int *qmat, const UINT8 *quant_matrix, int qscale)
{
    int i;

    for(i=0;i<64;i++) {
        qmat[i] = (int)((1 << 22) * 16384.0 / (aanscales[i] * qscale * quant_matrix[i]));
    }
}


int MPV_encode_init(AVEncodeContext *avctx)
{
    MpegEncContext *s = avctx->priv_data;
    int pict_size, c_size;
    UINT8 *pict;

    dsputil_init();

    s->bit_rate = avctx->bit_rate;
    s->frame_rate = avctx->rate;
    s->width = avctx->width;
    s->height = avctx->height;
    s->gop_size = avctx->gop_size;
    if (s->gop_size <= 1) {
        s->intra_only = 1;
        s->gop_size = 12;
    } else {
        s->intra_only = 0;
    }
    s->full_search = 0;
    if (avctx->flags & CODEC_FLAG_HQ)
        s->full_search = 1;

    switch(avctx->codec->id) {
    case CODEC_ID_MPEG1VIDEO:
        s->out_format = FMT_MPEG1;
        break;
    case CODEC_ID_MJPEG:
        s->out_format = FMT_MJPEG;
        s->intra_only = 1; /* force intra only for jpeg */
        if (mjpeg_init(s) < 0)
            return -1;
        break;
    case CODEC_ID_H263:
        s->out_format = FMT_H263;
        break;
    case CODEC_ID_RV10:
        s->out_format = FMT_H263;
        s->h263_rv10 = 1;
        break;
    case CODEC_ID_DIVX:
        s->out_format = FMT_H263;
        s->h263_pred = 1;
        break;
    default:
        return -1;
    }

    switch(s->frame_rate) {
    case 24:
        s->frame_rate_index = 2;
        break;
    case 25:
        s->frame_rate_index = 3;
        break;
    case 30:
        s->frame_rate_index = 5;
        break;
    case 50:
        s->frame_rate_index = 6;
        break;
    case 60:
        s->frame_rate_index = 8;
        break;
    default:
        /* we accept lower frame rates than 24 for low bit rate mpeg */
        if (s->frame_rate >= 1 && s->frame_rate < 24) {
            s->frame_rate_index = 2;
        } else {
            return -1;
        }
        break;
    }

    /* init */
    s->mb_width = s->width / 16;
    s->mb_height = s->height / 16;
    
    c_size = s->width * s->height;
    pict_size = (c_size * 3) / 2;
    pict = malloc(pict_size);
    if (pict == NULL)
        goto fail;
    s->last_picture[0] = pict;
    s->last_picture[1] = pict + c_size;
    s->last_picture[2] = pict + c_size + (c_size / 4);
    
    pict = malloc(pict_size);
    if (pict == NULL) 
        goto fail;
    s->current_picture[0] = pict;
    s->current_picture[1] = pict + c_size;
    s->current_picture[2] = pict + c_size + (c_size / 4);

    if (s->out_format == FMT_H263) {
        int size;
        /* MV prediction */
        size = (2 * s->mb_width + 2) * (2 * s->mb_height + 2);
        s->motion_val = malloc(size * 2 * sizeof(INT16));
        if (s->motion_val == NULL)
            goto fail;
        memset(s->motion_val, 0, size * 2 * sizeof(INT16));
    }

    if (s->h263_pred) {
        int y_size, c_size, i, size;

        y_size = (2 * s->mb_width + 2) * (2 * s->mb_height + 2);
        c_size = (s->mb_width + 2) * (s->mb_height + 2);
        size = y_size + 2 * c_size;
        s->dc_val[0] = malloc(size * sizeof(INT16));
        if (s->dc_val[0] == NULL)
            goto fail;
        s->dc_val[1] = s->dc_val[0] + y_size;
        s->dc_val[2] = s->dc_val[1] + c_size;
        for(i=0;i<size;i++)
            s->dc_val[0][i] = 1024;
    }

    /* rate control init */
    rate_control_init(s);

    s->picture_number = 0;
    s->fake_picture_number = 0;
    /* motion detector init */
    s->f_code = 1;

    return 0;
 fail:
    if (s->motion_val)
        free(s->motion_val);
    if (s->dc_val[0])
        free(s->dc_val[0]);
    if (s->last_picture[0])
        free(s->last_picture[0]);
    if (s->current_picture[0])
        free(s->current_picture[0]);
    return -1;
}

int MPV_encode_end(AVEncodeContext *avctx)
{
    MpegEncContext *s = avctx->priv_data;
#if 0
    /* end of sequence */
    if (s->out_format == FMT_MPEG1) {
        put_header(s, SEQ_END_CODE);
    }

    if (!s->flush_frames)
        flush_put_bits(&s->pb);
#endif    
    if (s->motion_val)
        free(s->motion_val);
    if (s->h263_pred)
        free(s->dc_val[0]);
    free(s->last_picture[0]);
    free(s->current_picture[0]);
    if (s->out_format == FMT_MJPEG)
        mjpeg_close(s);
    return 0;
}

int MPV_encode_picture(AVEncodeContext *avctx,
                       unsigned char *buf, int buf_size, void *data)
{
    MpegEncContext *s = avctx->priv_data;
    int i;

    memcpy(s->new_picture, data, 3 * sizeof(UINT8 *));

    init_put_bits(&s->pb, buf, buf_size, NULL, NULL);

    /* group of picture */
    if (s->out_format == FMT_MPEG1) {
        unsigned int vbv_buffer_size;
        unsigned int time_code, fps, n;

        if ((s->picture_number % s->gop_size) == 0) {
            /* mpeg1 header repeated every gop */
            put_header(s, SEQ_START_CODE);
            
            put_bits(&s->pb, 12, s->width);
            put_bits(&s->pb, 12, s->height);
            put_bits(&s->pb, 4, 1); /* 1/1 aspect ratio */
            put_bits(&s->pb, 4, s->frame_rate_index);
            put_bits(&s->pb, 18, 0x3ffff);
            put_bits(&s->pb, 1, 1); /* marker */
            /* vbv buffer size: slightly greater than an I frame. We add
               some margin just in case */
            vbv_buffer_size = (3 * s->I_frame_bits) / (2 * 8);
            put_bits(&s->pb, 10, (vbv_buffer_size + 16383) / 16384); 
            put_bits(&s->pb, 1, 1); /* constrained parameter flag */
            put_bits(&s->pb, 1, 0); /* no custom intra matrix */
            put_bits(&s->pb, 1, 0); /* no custom non intra matrix */

            put_header(s, GOP_START_CODE);
            put_bits(&s->pb, 1, 0); /* do drop frame */
            /* time code : we must convert from the real frame rate to a
               fake mpeg frame rate in case of low frame rate */
            fps = frame_rate_tab[s->frame_rate_index];
            time_code = s->fake_picture_number;
            s->gop_picture_number = time_code;
            put_bits(&s->pb, 5, (time_code / (fps * 3600)) % 24);
            put_bits(&s->pb, 6, (time_code / (fps * 60)) % 60);
            put_bits(&s->pb, 1, 1);
            put_bits(&s->pb, 6, (time_code / fps) % 60);
            put_bits(&s->pb, 6, (time_code % fps));
            put_bits(&s->pb, 1, 1); /* closed gop */
            put_bits(&s->pb, 1, 0); /* broken link */
        }

        if (s->frame_rate < 24 && s->picture_number > 0) {
            /* insert empty P pictures to slow down to the desired
               frame rate. Each fake pictures takes about 20 bytes */
            fps = frame_rate_tab[s->frame_rate_index];
            n = ((s->picture_number * fps) / s->frame_rate) - 1;
            while (s->fake_picture_number < n) {
                mpeg1_skip_picture(s, s->fake_picture_number - 
                                   s->gop_picture_number); 
                s->fake_picture_number++;
            }

        }
        s->fake_picture_number++;
    }
    
    
    if (!s->intra_only) {
        /* first picture of GOP is intra */
        if ((s->picture_number % s->gop_size) == 0)
            s->pict_type = I_TYPE;
        else
            s->pict_type = P_TYPE;
    } else {
        s->pict_type = I_TYPE;
    }
    avctx->key_frame = (s->pict_type == I_TYPE);
    
    encode_picture(s, s->picture_number);
    
    /* swap current and last picture */
    for(i=0;i<3;i++) {
        UINT8 *tmp;
        
        tmp = s->last_picture[i];
        s->last_picture[i] = s->current_picture[i];
        s->current_picture[i] = tmp;
    }
    s->picture_number++;

    if (s->out_format == FMT_MJPEG)
        mjpeg_picture_trailer(s);

    flush_put_bits(&s->pb);
    s->total_bits += (s->pb.buf_ptr - s->pb.buf) * 8;
    avctx->quality = s->qscale;
    return s->pb.buf_ptr - s->pb.buf;
}

/* insert a fake P picture */
static void mpeg1_skip_picture(MpegEncContext *s, int pict_num)
{
    unsigned int mb_incr;

    /* mpeg1 picture header */
    put_header(s, PICTURE_START_CODE);
    /* temporal reference */
    put_bits(&s->pb, 10, pict_num & 0x3ff); 
    
    put_bits(&s->pb, 3, P_TYPE);
    put_bits(&s->pb, 16, 0xffff); /* non constant bit rate */
    
    put_bits(&s->pb, 1, 1); /* integer coordinates */
    put_bits(&s->pb, 3, 1); /* forward_f_code */
    
    put_bits(&s->pb, 1, 0); /* extra bit picture */
    
    /* only one slice */
    put_header(s, SLICE_MIN_START_CODE);
    put_bits(&s->pb, 5, 1); /* quantizer scale */
    put_bits(&s->pb, 1, 0); /* slice extra information */
    
    mb_incr = 1;
    put_bits(&s->pb, mbAddrIncrTable[mb_incr][1], 
             mbAddrIncrTable[mb_incr][0]);
    
    /* empty macroblock */
    put_bits(&s->pb, 3, 1); /* motion only */
    
    /* zero motion x & y */
    put_bits(&s->pb, 1, 1); 
    put_bits(&s->pb, 1, 1); 

    /* output a number of empty slice */
    mb_incr = s->mb_width * s->mb_height - 1;
    while (mb_incr > 33) {
        put_bits(&s->pb, 11, 0x008);

⌨️ 快捷键说明

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