|
|
|
@@ -45,9 +45,8 @@ typedef struct SVQ1Context { |
|
|
|
AVCodecContext *avctx; |
|
|
|
DSPContext dsp; |
|
|
|
HpelDSPContext hdsp; |
|
|
|
AVFrame picture; |
|
|
|
AVFrame current_picture; |
|
|
|
AVFrame last_picture; |
|
|
|
AVFrame *current_picture; |
|
|
|
AVFrame *last_picture; |
|
|
|
PutBitContext pb; |
|
|
|
GetBitContext gb; |
|
|
|
|
|
|
|
@@ -264,13 +263,14 @@ static int svq1_encode_plane(SVQ1Context *s, int plane, |
|
|
|
unsigned char *decoded_plane, |
|
|
|
int width, int height, int src_stride, int stride) |
|
|
|
{ |
|
|
|
const AVFrame *f = s->avctx->coded_frame; |
|
|
|
int x, y; |
|
|
|
int i; |
|
|
|
int block_width, block_height; |
|
|
|
int level; |
|
|
|
int threshold[6]; |
|
|
|
uint8_t *src = s->scratchbuf + stride * 16; |
|
|
|
const int lambda = (s->picture.quality * s->picture.quality) >> |
|
|
|
const int lambda = (f->quality * f->quality) >> |
|
|
|
(2 * FF_LAMBDA_SHIFT); |
|
|
|
|
|
|
|
/* figure out the acceptable level thresholds in advance */ |
|
|
|
@@ -281,7 +281,7 @@ static int svq1_encode_plane(SVQ1Context *s, int plane, |
|
|
|
block_width = (width + 15) / 16; |
|
|
|
block_height = (height + 15) / 16; |
|
|
|
|
|
|
|
if (s->picture.pict_type == AV_PICTURE_TYPE_P) { |
|
|
|
if (f->pict_type == AV_PICTURE_TYPE_P) { |
|
|
|
s->m.avctx = s->avctx; |
|
|
|
s->m.current_picture_ptr = &s->m.current_picture; |
|
|
|
s->m.last_picture_ptr = &s->m.last_picture; |
|
|
|
@@ -297,13 +297,13 @@ static int svq1_encode_plane(SVQ1Context *s, int plane, |
|
|
|
s->m.mb_stride = s->m.mb_width + 1; |
|
|
|
s->m.b8_stride = 2 * s->m.mb_width + 1; |
|
|
|
s->m.f_code = 1; |
|
|
|
s->m.pict_type = s->picture.pict_type; |
|
|
|
s->m.pict_type = f->pict_type; |
|
|
|
s->m.me_method = s->avctx->me_method; |
|
|
|
s->m.me.scene_change_score = 0; |
|
|
|
s->m.flags = s->avctx->flags; |
|
|
|
// s->m.out_format = FMT_H263; |
|
|
|
// s->m.unrestricted_mv = 1; |
|
|
|
s->m.lambda = s->picture.quality; |
|
|
|
s->m.lambda = f->quality; |
|
|
|
s->m.qscale = s->m.lambda * 139 + |
|
|
|
FF_LAMBDA_SCALE * 64 >> |
|
|
|
FF_LAMBDA_SHIFT + 7; |
|
|
|
@@ -396,13 +396,13 @@ static int svq1_encode_plane(SVQ1Context *s, int plane, |
|
|
|
ff_init_block_index(&s->m); |
|
|
|
ff_update_block_index(&s->m); |
|
|
|
|
|
|
|
if (s->picture.pict_type == AV_PICTURE_TYPE_I || |
|
|
|
if (f->pict_type == AV_PICTURE_TYPE_I || |
|
|
|
(s->m.mb_type[x + y * s->m.mb_stride] & |
|
|
|
CANDIDATE_MB_TYPE_INTRA)) { |
|
|
|
for (i = 0; i < 6; i++) |
|
|
|
init_put_bits(&s->reorder_pb[i], reorder_buffer[0][i], |
|
|
|
7 * 32); |
|
|
|
if (s->picture.pict_type == AV_PICTURE_TYPE_P) { |
|
|
|
if (f->pict_type == AV_PICTURE_TYPE_P) { |
|
|
|
const uint8_t *vlc = ff_svq1_block_type_vlc[SVQ1_BLOCK_INTRA]; |
|
|
|
put_bits(&s->reorder_pb[5], vlc[1], vlc[0]); |
|
|
|
score[0] = vlc[1] * lambda; |
|
|
|
@@ -418,7 +418,7 @@ static int svq1_encode_plane(SVQ1Context *s, int plane, |
|
|
|
|
|
|
|
best = 0; |
|
|
|
|
|
|
|
if (s->picture.pict_type == AV_PICTURE_TYPE_P) { |
|
|
|
if (f->pict_type == AV_PICTURE_TYPE_P) { |
|
|
|
const uint8_t *vlc = ff_svq1_block_type_vlc[SVQ1_BLOCK_INTER]; |
|
|
|
int mx, my, pred_x, pred_y, dxy; |
|
|
|
int16_t *motion_ptr; |
|
|
|
@@ -498,13 +498,48 @@ static int svq1_encode_plane(SVQ1Context *s, int plane, |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static av_cold int svq1_encode_end(AVCodecContext *avctx) |
|
|
|
{ |
|
|
|
SVQ1Context *const s = avctx->priv_data; |
|
|
|
int i; |
|
|
|
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, "RD: %f\n", |
|
|
|
s->rd_total / (double)(avctx->width * avctx->height * |
|
|
|
avctx->frame_number)); |
|
|
|
|
|
|
|
av_freep(&s->m.me.scratchpad); |
|
|
|
av_freep(&s->m.me.map); |
|
|
|
av_freep(&s->m.me.score_map); |
|
|
|
av_freep(&s->mb_type); |
|
|
|
av_freep(&s->dummy); |
|
|
|
av_freep(&s->scratchbuf); |
|
|
|
|
|
|
|
for (i = 0; i < 3; i++) { |
|
|
|
av_freep(&s->motion_val8[i]); |
|
|
|
av_freep(&s->motion_val16[i]); |
|
|
|
} |
|
|
|
|
|
|
|
av_frame_free(&s->current_picture); |
|
|
|
av_frame_free(&s->last_picture); |
|
|
|
av_frame_free(&avctx->coded_frame); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static av_cold int svq1_encode_init(AVCodecContext *avctx) |
|
|
|
{ |
|
|
|
SVQ1Context *const s = avctx->priv_data; |
|
|
|
|
|
|
|
ff_dsputil_init(&s->dsp, avctx); |
|
|
|
ff_hpeldsp_init(&s->hdsp, avctx->flags); |
|
|
|
avctx->coded_frame = &s->picture; |
|
|
|
|
|
|
|
avctx->coded_frame = av_frame_alloc(); |
|
|
|
s->current_picture = av_frame_alloc(); |
|
|
|
s->last_picture = av_frame_alloc(); |
|
|
|
if (!avctx->coded_frame || !s->current_picture || !s->last_picture) { |
|
|
|
svq1_encode_end(avctx); |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
} |
|
|
|
|
|
|
|
s->frame_width = avctx->width; |
|
|
|
s->frame_height = avctx->height; |
|
|
|
@@ -536,8 +571,7 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
|
|
|
const AVFrame *pict, int *got_packet) |
|
|
|
{ |
|
|
|
SVQ1Context *const s = avctx->priv_data; |
|
|
|
AVFrame *const p = &s->picture; |
|
|
|
AVFrame temp; |
|
|
|
AVFrame *const p = avctx->coded_frame; |
|
|
|
int i, ret; |
|
|
|
|
|
|
|
if ((ret = ff_alloc_packet2(avctx, pkt, s->y_block_width * s->y_block_height * |
|
|
|
@@ -549,35 +583,33 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
if (!s->current_picture.data[0]) { |
|
|
|
if ((ret = ff_get_buffer(avctx, &s->current_picture, 0))< 0 || |
|
|
|
(ret = ff_get_buffer(avctx, &s->last_picture, 0)) < 0) { |
|
|
|
if (!s->current_picture->data[0]) { |
|
|
|
if ((ret = ff_get_buffer(avctx, s->current_picture, 0))< 0 || |
|
|
|
(ret = ff_get_buffer(avctx, s->last_picture, 0)) < 0) { |
|
|
|
return ret; |
|
|
|
} |
|
|
|
s->scratchbuf = av_malloc(s->current_picture.linesize[0] * 16 * 2); |
|
|
|
s->scratchbuf = av_malloc(s->current_picture->linesize[0] * 16 * 2); |
|
|
|
} |
|
|
|
|
|
|
|
av_frame_move_ref(&temp, &s->current_picture); |
|
|
|
av_frame_move_ref(&s->current_picture, &s->last_picture); |
|
|
|
av_frame_move_ref(&s->last_picture, &temp); |
|
|
|
FFSWAP(AVFrame*, s->current_picture, s->last_picture); |
|
|
|
|
|
|
|
init_put_bits(&s->pb, pkt->data, pkt->size); |
|
|
|
|
|
|
|
*p = *pict; |
|
|
|
p->pict_type = avctx->gop_size && avctx->frame_number % avctx->gop_size ? |
|
|
|
AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; |
|
|
|
p->key_frame = p->pict_type == AV_PICTURE_TYPE_I; |
|
|
|
p->quality = pict->quality; |
|
|
|
|
|
|
|
svq1_write_header(s, p->pict_type); |
|
|
|
for (i = 0; i < 3; i++) |
|
|
|
if (svq1_encode_plane(s, i, |
|
|
|
s->picture.data[i], |
|
|
|
s->last_picture.data[i], |
|
|
|
s->current_picture.data[i], |
|
|
|
pict->data[i], |
|
|
|
s->last_picture->data[i], |
|
|
|
s->current_picture->data[i], |
|
|
|
s->frame_width / (i ? 4 : 1), |
|
|
|
s->frame_height / (i ? 4 : 1), |
|
|
|
s->picture.linesize[i], |
|
|
|
s->current_picture.linesize[i]) < 0) |
|
|
|
pict->linesize[i], |
|
|
|
s->current_picture->linesize[i]) < 0) |
|
|
|
return -1; |
|
|
|
|
|
|
|
// avpriv_align_put_bits(&s->pb); |
|
|
|
@@ -594,33 +626,6 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static av_cold int svq1_encode_end(AVCodecContext *avctx) |
|
|
|
{ |
|
|
|
SVQ1Context *const s = avctx->priv_data; |
|
|
|
int i; |
|
|
|
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, "RD: %f\n", |
|
|
|
s->rd_total / (double)(avctx->width * avctx->height * |
|
|
|
avctx->frame_number)); |
|
|
|
|
|
|
|
av_freep(&s->m.me.scratchpad); |
|
|
|
av_freep(&s->m.me.map); |
|
|
|
av_freep(&s->m.me.score_map); |
|
|
|
av_freep(&s->mb_type); |
|
|
|
av_freep(&s->dummy); |
|
|
|
av_freep(&s->scratchbuf); |
|
|
|
|
|
|
|
for (i = 0; i < 3; i++) { |
|
|
|
av_freep(&s->motion_val8[i]); |
|
|
|
av_freep(&s->motion_val16[i]); |
|
|
|
} |
|
|
|
|
|
|
|
av_frame_unref(&s->current_picture); |
|
|
|
av_frame_unref(&s->last_picture); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
AVCodec ff_svq1_encoder = { |
|
|
|
.name = "svq1", |
|
|
|
.long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"), |
|
|
|
|