mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-libstb-hal.git
synced 2025-08-27 15:32:43 +02:00
Origin commit data
------------------
Branch: master
Commit: bc17c13de4
Author: vanhofen <vanhofen@gmx.de>
Date: 2021-05-17 (Mon, 17 May 2021)
Origin message was:
------------------
- formatting code using astyle
------------------
No further description and justification available within origin commit message!
------------------
This commit was generated by Migit
325 lines
7.8 KiB
C
325 lines
7.8 KiB
C
/*
|
|
* FLV to MPEG4 converter
|
|
*
|
|
* Copyright (c) 2006 vixy project
|
|
*
|
|
* This file contains the code that based on FFmpeg (http://ffmpeg.mplayerhq.hu/)
|
|
* See original copyright notice in /FFMPEG_CREDITS and /FFMPEG_IMPORTS
|
|
*
|
|
* This file is part of VIXY FLV Converter.
|
|
*
|
|
* 'VIXY FLV Converter' is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* 'VIXY FLV Converter' 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with FFmpeg; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "m4v.h"
|
|
#include "bitwriter.h"
|
|
#include "flv.h"
|
|
#include "m4vencode.h"
|
|
#include "../flv2mpeg4.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
typedef struct _CONVCTX
|
|
{
|
|
int width;
|
|
int height;
|
|
|
|
int frame;
|
|
int icounter;
|
|
|
|
M4V_VOL vol;
|
|
} CONVCTX;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
uint8 *out_buf;
|
|
M4V_VOL vol;
|
|
CONVCTX conv;
|
|
} CTX;
|
|
|
|
#define VOL_TIME_BITS 5
|
|
#define PACKETBUFFER_SIZE (256*1024*4)
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static const uint8 ff_mpeg4_y_dc_scale_table[32] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
|
0, 8, 8, 8, 8, 10, 12, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 36, 38, 40, 42, 44, 46
|
|
};
|
|
|
|
static const uint8 ff_mpeg4_c_dc_scale_table[32] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
|
0, 8, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25
|
|
};
|
|
|
|
|
|
static void copy_vol(PICTURE *flv_pic, M4V_VOL *vol)
|
|
{
|
|
vol->width = flv_pic->width;
|
|
vol->height = flv_pic->height;
|
|
vol->time_bits = VOL_TIME_BITS; // 0-31
|
|
}
|
|
|
|
static void copy_vop(PICTURE *flv_pic, M4V_VOP *vop, CONVCTX *c)
|
|
{
|
|
vop->qscale = flv_pic->qscale;
|
|
|
|
vop->time = c->frame % 30;
|
|
vop->icount = (c->icounter + 29) / 30;
|
|
vop->intra_dc_threshold = 99;
|
|
|
|
if (flv_pic->picture_type == FLV_I_TYPE)
|
|
{
|
|
vop->picture_type = M4V_I_TYPE;
|
|
}
|
|
else
|
|
{
|
|
vop->picture_type = M4V_P_TYPE;
|
|
vop->f_code = 1;
|
|
}
|
|
}
|
|
|
|
static void copy_microblock(MICROBLOCK *flv_mb, M4V_MICROBLOCK *m4v_mb)
|
|
{
|
|
int i;
|
|
|
|
m4v_mb->dquant = flv_mb->dquant;
|
|
memcpy(m4v_mb->block, flv_mb->block, sizeof(m4v_mb->block)); // !!!!!!!
|
|
m4v_mb->intra = flv_mb->intra;
|
|
m4v_mb->skip = flv_mb->skip;
|
|
m4v_mb->mv_type = flv_mb->mv_type;
|
|
|
|
memcpy(m4v_mb->mv_x, flv_mb->mv_x, sizeof(m4v_mb->mv_x)); // !!!!!!
|
|
memcpy(m4v_mb->mv_y, flv_mb->mv_y, sizeof(m4v_mb->mv_y)); // !!!!!!
|
|
|
|
// dc rescale
|
|
if (m4v_mb->intra)
|
|
{
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
m4v_mb->block[i].block[0] *= 8;
|
|
m4v_mb->block[i].block[0] /= ff_mpeg4_y_dc_scale_table[m4v_mb->qscale];
|
|
}
|
|
|
|
for (i = 4; i < 6; i++)
|
|
{
|
|
m4v_mb->block[i].block[0] *= 8;
|
|
m4v_mb->block[i].block[0] /= ff_mpeg4_c_dc_scale_table[m4v_mb->qscale];
|
|
}
|
|
}
|
|
}
|
|
|
|
static int write_pad_not_coded_frames(flv2mpeg4_CTX *pub_ctx, CONVCTX *c, BW *bw, uint32 time)
|
|
{
|
|
// if any timecode padding is needed, then pad.
|
|
while (c->frame * 1000 / 30 < time)
|
|
{
|
|
M4V_VOP vop;
|
|
memset(&vop, 0, sizeof(vop));
|
|
vop.picture_type = M4V_P_TYPE;
|
|
vop.time = c->frame % 30;
|
|
vop.icount = (c->icounter + 29) / 30;
|
|
m4v_encode_vop_header(bw, &vop, VOL_TIME_BITS, 1);
|
|
m4v_stuffing(bw);
|
|
|
|
flash_bw(bw);
|
|
|
|
// write frame
|
|
if (pub_ctx->write_packet_cb(pub_ctx->usr_data,
|
|
0,
|
|
0,//c->frame,
|
|
bw->buf,
|
|
bw->pos) < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
clear_bw(bw);
|
|
|
|
c->frame++;
|
|
c->icounter++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int write_m4v_picture_frame(flv2mpeg4_CTX *pub_ctx, CONVCTX *c, BR *br, BW *bw, PICTURE *flvpic, uint32 time)
|
|
{
|
|
MICROBLOCK mb;
|
|
M4V_VOP vop;
|
|
M4V_MICROBLOCK m4v_mb;
|
|
int x, y;
|
|
int mb_width = (flvpic->width + 15) / 16;
|
|
int mb_height = (flvpic->height + 15) / 16;
|
|
|
|
memset(&vop, 0, sizeof(vop));
|
|
|
|
copy_vop(flvpic, &vop, c);
|
|
m4v_encode_vop_header(bw, &vop, VOL_TIME_BITS, 0);
|
|
|
|
// transcode flv to mpeg4
|
|
for (y = 0; y < mb_height; y++)
|
|
{
|
|
for (x = 0; x < mb_width; x++)
|
|
{
|
|
memset(&mb, 0, sizeof(mb));
|
|
memset(&m4v_mb, 0, sizeof(m4v_mb));
|
|
|
|
if (vop.picture_type == M4V_I_TYPE)
|
|
{
|
|
mb.intra = 1;
|
|
if (decode_I_mb(br, &mb, flvpic->escape_type, flvpic->qscale) < 0) return -1;
|
|
m4v_mb.qscale = vop.qscale;
|
|
copy_microblock(&mb, &m4v_mb);
|
|
m4v_encode_I_dcpred(&m4v_mb, &c->vol.dcpred, x, y);
|
|
m4v_encode_I_mb(bw, &m4v_mb);
|
|
}
|
|
else
|
|
{
|
|
if (decode_P_mb(br, &mb, flvpic->escape_type, flvpic->qscale) < 0) return -1;
|
|
m4v_mb.qscale = vop.qscale;
|
|
copy_microblock(&mb, &m4v_mb);
|
|
m4v_encode_I_dcpred(&m4v_mb, &c->vol.dcpred, x, y);
|
|
m4v_encode_P_mb(bw, &m4v_mb);
|
|
}
|
|
}
|
|
}
|
|
|
|
m4v_stuffing(bw);
|
|
flash_bw(bw);
|
|
|
|
// write frame
|
|
if (pub_ctx->write_packet_cb(pub_ctx->usr_data,
|
|
vop.picture_type == M4V_I_TYPE,
|
|
0,//c->frame,
|
|
bw->buf,
|
|
bw->pos) < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
c->frame++;
|
|
c->icounter++;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int write_m4v_frame(flv2mpeg4_CTX *pub_ctx, CONVCTX *c, BR *br, BW *bw, uint32 time)
|
|
{
|
|
PICTURE picture;
|
|
|
|
memset(&picture, 0, sizeof(picture));
|
|
init_dcpred(&c->vol.dcpred);
|
|
|
|
if (decode_picture_header(br, &picture) < 0) return -1;
|
|
if (c->width != picture.width || c->height != picture.height) return -1; //size changed..
|
|
|
|
copy_vol(&picture, &c->vol);
|
|
|
|
if (picture.picture_type == FLV_I_TYPE)
|
|
{
|
|
c->icounter = 0;
|
|
}
|
|
else
|
|
{
|
|
if (write_pad_not_coded_frames(pub_ctx, c, bw, time) < 0) return -1;
|
|
}
|
|
|
|
if (write_m4v_picture_frame(pub_ctx, c, br, bw, &picture, time) < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int flv2mpeg4_process_flv_packet(flv2mpeg4_CTX *ctx, uint8 picture_type, const uint8 *buf, uint32 size, uint32 time)
|
|
{
|
|
CTX *p = ctx->priv;
|
|
BR br;
|
|
BW bw;
|
|
init_br(&br, buf, size);
|
|
init_bw(&bw, p->out_buf, PACKETBUFFER_SIZE);
|
|
write_m4v_frame(ctx, &p->conv, &br, &bw, time);
|
|
return 0;
|
|
}
|
|
|
|
int flv2mpeg4_prepare_extra_data(flv2mpeg4_CTX *ctx)
|
|
{
|
|
CTX *p = ctx->priv;
|
|
BW bw;
|
|
CONVCTX *c = &(p->conv);
|
|
|
|
M4V_VOP vop;
|
|
memset(&vop, 0, sizeof(vop));
|
|
|
|
init_bw(&bw, p->out_buf, PACKETBUFFER_SIZE);
|
|
|
|
c->vol.width = c->width;
|
|
c->vol.height = c->height;
|
|
c->vol.time_bits = VOL_TIME_BITS; // 0-31
|
|
|
|
m4v_encode_m4v_header(&bw, &c->vol, 0);
|
|
|
|
m4v_stuffing(&bw);
|
|
flash_bw(&bw);
|
|
|
|
alloc_dcpred(&c->vol.dcpred, (c->width + 15) / 16, (c->height + 15) / 16);
|
|
|
|
return ctx->write_extradata_cb(ctx->usr_data, c->width, c->height, 200 * 1000, bw.buf, bw.pos);
|
|
}
|
|
|
|
void flv2mpeg4_set_frame(flv2mpeg4_CTX *ctx, int frame, int icounter)
|
|
{
|
|
CTX *p = ctx->priv;
|
|
p->conv.frame = frame;
|
|
p->conv.icounter = icounter;
|
|
}
|
|
|
|
flv2mpeg4_CTX *flv2mpeg4_init_ctx(void *priv_data, int width, int height, flv2mpeg4_write_packet_cb wp_cb, flv2mpeg4_write_extradata_cb we_cb)
|
|
{
|
|
flv2mpeg4_CTX *pub_ctx = malloc(sizeof(flv2mpeg4_CTX));
|
|
memset(pub_ctx, 0x0, sizeof(flv2mpeg4_CTX));
|
|
pub_ctx->usr_data = priv_data;
|
|
pub_ctx->write_packet_cb = wp_cb;
|
|
pub_ctx->write_extradata_cb = we_cb;
|
|
pub_ctx->priv = malloc(sizeof(CTX));
|
|
memset(pub_ctx->priv, 0x0, sizeof(CTX));
|
|
CTX *ctx = pub_ctx->priv;
|
|
|
|
ctx->conv.width = width;
|
|
ctx->conv.height = height;
|
|
ctx->out_buf = malloc(PACKETBUFFER_SIZE);
|
|
memset(ctx->out_buf, 0x0, PACKETBUFFER_SIZE);
|
|
memset(&(ctx->vol), 0x0, sizeof(ctx->vol));
|
|
|
|
return pub_ctx;
|
|
}
|
|
|
|
void flv2mpeg4_release_ctx(flv2mpeg4_CTX **pub_ctx)
|
|
{
|
|
CTX *ctx = (*pub_ctx)->priv;
|
|
|
|
free_dcpred(&ctx->conv.vol.dcpred);
|
|
free(ctx->out_buf);
|
|
free(ctx);
|
|
free(*pub_ctx);
|
|
*pub_ctx = NULL;
|
|
}
|
|
|
|
|
|
|