@@ -46,6 +46,7 @@ version <next>: | |||||
- NVDEC AV1 hwaccel | - NVDEC AV1 hwaccel | ||||
- DXVA2/D3D11VA hardware accelerated AV1 decoding | - DXVA2/D3D11VA hardware accelerated AV1 decoding | ||||
- speechnorm filter | - speechnorm filter | ||||
- SpeedHQ encoder | |||||
version 4.3: | version 4.3: | ||||
@@ -972,7 +972,7 @@ following image formats are supported: | |||||
@item MPEG-4 part 2 Microsoft variant version 1 @tab @tab X | @item MPEG-4 part 2 Microsoft variant version 1 @tab @tab X | ||||
@item MPEG-4 part 2 Microsoft variant version 2 @tab X @tab X | @item MPEG-4 part 2 Microsoft variant version 2 @tab X @tab X | ||||
@item MPEG-4 part 2 Microsoft variant version 3 @tab X @tab X | @item MPEG-4 part 2 Microsoft variant version 3 @tab X @tab X | ||||
@item Newtek SpeedHQ @tab @tab X | |||||
@item Newtek SpeedHQ @tab X @tab X | |||||
@item Nintendo Gamecube THP video @tab @tab X | @item Nintendo Gamecube THP video @tab @tab X | ||||
@item NotchLC @tab @tab X | @item NotchLC @tab @tab X | ||||
@item NuppelVideo/RTjpeg @tab @tab X | @item NuppelVideo/RTjpeg @tab @tab X | ||||
@@ -625,6 +625,7 @@ OBJS-$(CONFIG_SONIC_DECODER) += sonic.o | |||||
OBJS-$(CONFIG_SONIC_ENCODER) += sonic.o | OBJS-$(CONFIG_SONIC_ENCODER) += sonic.o | ||||
OBJS-$(CONFIG_SONIC_LS_ENCODER) += sonic.o | OBJS-$(CONFIG_SONIC_LS_ENCODER) += sonic.o | ||||
OBJS-$(CONFIG_SPEEDHQ_DECODER) += speedhq.o mpeg12.o mpeg12data.o simple_idct.o | OBJS-$(CONFIG_SPEEDHQ_DECODER) += speedhq.o mpeg12.o mpeg12data.o simple_idct.o | ||||
OBJS-$(CONFIG_SPEEDHQ_ENCODER) += speedhq.o mpeg12data.o speedhqenc.o | |||||
OBJS-$(CONFIG_SP5X_DECODER) += sp5xdec.o | OBJS-$(CONFIG_SP5X_DECODER) += sp5xdec.o | ||||
OBJS-$(CONFIG_SRGC_DECODER) += mscc.o | OBJS-$(CONFIG_SRGC_DECODER) += mscc.o | ||||
OBJS-$(CONFIG_SRT_DECODER) += srtdec.o ass.o htmlsubtitles.o | OBJS-$(CONFIG_SRT_DECODER) += srtdec.o ass.o htmlsubtitles.o | ||||
@@ -297,6 +297,7 @@ extern AVCodec ff_snow_encoder; | |||||
extern AVCodec ff_snow_decoder; | extern AVCodec ff_snow_decoder; | ||||
extern AVCodec ff_sp5x_decoder; | extern AVCodec ff_sp5x_decoder; | ||||
extern AVCodec ff_speedhq_decoder; | extern AVCodec ff_speedhq_decoder; | ||||
extern AVCodec ff_speedhq_encoder; | |||||
extern AVCodec ff_srgc_decoder; | extern AVCodec ff_srgc_decoder; | ||||
extern AVCodec ff_sunrast_encoder; | extern AVCodec ff_sunrast_encoder; | ||||
extern AVCodec ff_sunrast_decoder; | extern AVCodec ff_sunrast_decoder; | ||||
@@ -125,6 +125,7 @@ enum OutputFormat { | |||||
FMT_H261, | FMT_H261, | ||||
FMT_H263, | FMT_H263, | ||||
FMT_MJPEG, | FMT_MJPEG, | ||||
FMT_SPEEDHQ, | |||||
}; | }; | ||||
@@ -444,6 +444,9 @@ typedef struct MpegEncContext { | |||||
int inter_intra_pred; | int inter_intra_pred; | ||||
int mspel; | int mspel; | ||||
/* SpeedHQ specific */ | |||||
int slice_start; | |||||
/* decompression specific */ | /* decompression specific */ | ||||
GetBitContext gb; | GetBitContext gb; | ||||
@@ -51,6 +51,7 @@ | |||||
#include "mathops.h" | #include "mathops.h" | ||||
#include "mpegutils.h" | #include "mpegutils.h" | ||||
#include "mjpegenc.h" | #include "mjpegenc.h" | ||||
#include "speedhqenc.h" | |||||
#include "msmpeg4.h" | #include "msmpeg4.h" | ||||
#include "pixblockdsp.h" | #include "pixblockdsp.h" | ||||
#include "qpeldsp.h" | #include "qpeldsp.h" | ||||
@@ -326,6 +327,15 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) | |||||
return AVERROR(EINVAL); | return AVERROR(EINVAL); | ||||
} | } | ||||
break; | break; | ||||
case AV_CODEC_ID_SPEEDHQ: | |||||
if (avctx->pix_fmt != AV_PIX_FMT_YUV420P && | |||||
avctx->pix_fmt != AV_PIX_FMT_YUV422P && | |||||
avctx->pix_fmt != AV_PIX_FMT_YUV444P) { | |||||
av_log(avctx, AV_LOG_ERROR, | |||||
"only YUV420/YUV422/YUV444 are supported (no alpha support yet)\n"); | |||||
return AVERROR(EINVAL); | |||||
} | |||||
break; | |||||
default: | default: | ||||
if (avctx->pix_fmt != AV_PIX_FMT_YUV420P) { | if (avctx->pix_fmt != AV_PIX_FMT_YUV420P) { | ||||
av_log(avctx, AV_LOG_ERROR, "only YUV420 is supported\n"); | av_log(avctx, AV_LOG_ERROR, "only YUV420 is supported\n"); | ||||
@@ -732,7 +742,7 @@ FF_ENABLE_DEPRECATION_WARNINGS | |||||
//return -1; | //return -1; | ||||
} | } | ||||
if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG1VIDEO || s->codec_id == AV_CODEC_ID_MPEG2VIDEO || s->codec_id == AV_CODEC_ID_MJPEG || s->codec_id==AV_CODEC_ID_AMV) { | |||||
if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG1VIDEO || s->codec_id == AV_CODEC_ID_MPEG2VIDEO || s->codec_id == AV_CODEC_ID_MJPEG || s->codec_id == AV_CODEC_ID_AMV || s->codec_id == AV_CODEC_ID_SPEEDHQ) { | |||||
// (a + x * 3 / 8) / x | // (a + x * 3 / 8) / x | ||||
s->intra_quant_bias = 3 << (QUANT_BIAS_SHIFT - 3); | s->intra_quant_bias = 3 << (QUANT_BIAS_SHIFT - 3); | ||||
s->inter_quant_bias = 0; | s->inter_quant_bias = 0; | ||||
@@ -783,6 +793,16 @@ FF_ENABLE_DEPRECATION_WARNINGS | |||||
avctx->delay = 0; | avctx->delay = 0; | ||||
s->low_delay = 1; | s->low_delay = 1; | ||||
break; | break; | ||||
case AV_CODEC_ID_SPEEDHQ: | |||||
s->out_format = FMT_SPEEDHQ; | |||||
s->intra_only = 1; /* force intra only for SHQ */ | |||||
if (!CONFIG_SPEEDHQ_ENCODER) | |||||
return AVERROR_ENCODER_NOT_FOUND; | |||||
if ((ret = ff_speedhq_encode_init(s)) < 0) | |||||
return ret; | |||||
avctx->delay = 0; | |||||
s->low_delay = 1; | |||||
break; | |||||
case AV_CODEC_ID_H261: | case AV_CODEC_ID_H261: | ||||
if (!CONFIG_H261_ENCODER) | if (!CONFIG_H261_ENCODER) | ||||
return AVERROR_ENCODER_NOT_FOUND; | return AVERROR_ENCODER_NOT_FOUND; | ||||
@@ -997,6 +1017,9 @@ FF_ENABLE_DEPRECATION_WARNINGS | |||||
} else if (s->out_format == FMT_H263 || s->out_format == FMT_H261) { | } else if (s->out_format == FMT_H263 || s->out_format == FMT_H261) { | ||||
s->intra_matrix[j] = | s->intra_matrix[j] = | ||||
s->inter_matrix[j] = ff_mpeg1_default_non_intra_matrix[i]; | s->inter_matrix[j] = ff_mpeg1_default_non_intra_matrix[i]; | ||||
} else if (CONFIG_SPEEDHQ_ENCODER && s->codec_id == AV_CODEC_ID_SPEEDHQ) { | |||||
s->intra_matrix[j] = | |||||
s->inter_matrix[j] = ff_mpeg1_default_intra_matrix[i]; | |||||
} else { | } else { | ||||
/* MPEG-1/2 */ | /* MPEG-1/2 */ | ||||
s->chroma_intra_matrix[j] = | s->chroma_intra_matrix[j] = | ||||
@@ -2562,6 +2585,10 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, | |||||
if (CONFIG_MJPEG_ENCODER) | if (CONFIG_MJPEG_ENCODER) | ||||
ff_mjpeg_encode_mb(s, s->block); | ff_mjpeg_encode_mb(s, s->block); | ||||
break; | break; | ||||
case AV_CODEC_ID_SPEEDHQ: | |||||
if (CONFIG_SPEEDHQ_ENCODER) | |||||
ff_speedhq_encode_mb(s, s->block); | |||||
break; | |||||
default: | default: | ||||
av_assert1(0); | av_assert1(0); | ||||
} | } | ||||
@@ -2816,6 +2843,8 @@ static void write_slice_end(MpegEncContext *s){ | |||||
ff_mpeg4_stuffing(&s->pb); | ff_mpeg4_stuffing(&s->pb); | ||||
}else if(CONFIG_MJPEG_ENCODER && s->out_format == FMT_MJPEG){ | }else if(CONFIG_MJPEG_ENCODER && s->out_format == FMT_MJPEG){ | ||||
ff_mjpeg_encode_stuffing(s); | ff_mjpeg_encode_stuffing(s); | ||||
} else if (CONFIG_SPEEDHQ_ENCODER && s->out_format == FMT_SPEEDHQ) { | |||||
ff_speedhq_end_slice(s); | |||||
} | } | ||||
flush_put_bits(&s->pb); | flush_put_bits(&s->pb); | ||||
@@ -2905,7 +2934,7 @@ int ff_mpv_reallocate_putbitbuffer(MpegEncContext *s, size_t threshold, size_t s | |||||
static int encode_thread(AVCodecContext *c, void *arg){ | static int encode_thread(AVCodecContext *c, void *arg){ | ||||
MpegEncContext *s= *(void**)arg; | MpegEncContext *s= *(void**)arg; | ||||
int mb_x, mb_y; | |||||
int mb_x, mb_y, mb_y_order; | |||||
int chr_h= 16>>s->chroma_y_shift; | int chr_h= 16>>s->chroma_y_shift; | ||||
int i, j; | int i, j; | ||||
MpegEncContext best_s = { 0 }, backup_s; | MpegEncContext best_s = { 0 }, backup_s; | ||||
@@ -2966,7 +2995,16 @@ static int encode_thread(AVCodecContext *c, void *arg){ | |||||
s->resync_mb_y=0; | s->resync_mb_y=0; | ||||
s->first_slice_line = 1; | s->first_slice_line = 1; | ||||
s->ptr_lastgob = s->pb.buf; | s->ptr_lastgob = s->pb.buf; | ||||
for(mb_y= s->start_mb_y; mb_y < s->end_mb_y; mb_y++) { | |||||
for (mb_y_order = s->start_mb_y; mb_y_order < s->end_mb_y; mb_y_order++) { | |||||
if (s->codec_id == AV_CODEC_ID_SPEEDHQ) { | |||||
int first_in_slice; | |||||
mb_y = ff_speedhq_mb_y_order_to_mb(mb_y_order, s->mb_height, &first_in_slice); | |||||
if (first_in_slice && mb_y_order != s->start_mb_y) | |||||
ff_speedhq_end_slice(s); | |||||
s->last_dc[0] = s->last_dc[1] = s->last_dc[2] = 1024 << s->intra_dc_precision; | |||||
} else { | |||||
mb_y = mb_y_order; | |||||
} | |||||
s->mb_x=0; | s->mb_x=0; | ||||
s->mb_y= mb_y; | s->mb_y= mb_y; | ||||
@@ -3855,6 +3893,11 @@ static int encode_picture(MpegEncContext *s, int picture_number) | |||||
s->qscale= 8; | s->qscale= 8; | ||||
} | } | ||||
if (s->out_format == FMT_SPEEDHQ) { | |||||
s->y_dc_scale_table= | |||||
s->c_dc_scale_table= ff_mpeg2_dc_scale_table[3]; | |||||
} | |||||
//FIXME var duplication | //FIXME var duplication | ||||
s->current_picture_ptr->f->key_frame = | s->current_picture_ptr->f->key_frame = | ||||
s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; //FIXME pic_ptr | s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; //FIXME pic_ptr | ||||
@@ -3872,6 +3915,10 @@ static int encode_picture(MpegEncContext *s, int picture_number) | |||||
ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable, | ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable, | ||||
s->pred, s->intra_matrix, s->chroma_intra_matrix); | s->pred, s->intra_matrix, s->chroma_intra_matrix); | ||||
break; | break; | ||||
case FMT_SPEEDHQ: | |||||
if (CONFIG_SPEEDHQ_ENCODER) | |||||
ff_speedhq_encode_picture_header(s); | |||||
break; | |||||
case FMT_H261: | case FMT_H261: | ||||
if (CONFIG_H261_ENCODER) | if (CONFIG_H261_ENCODER) | ||||
ff_h261_encode_picture_header(s, picture_number); | ff_h261_encode_picture_header(s, picture_number); | ||||
@@ -132,7 +132,7 @@ static const uint8_t speedhq_run[121] = { | |||||
31, | 31, | ||||
}; | }; | ||||
static RLTable rl_speedhq = { | |||||
RLTable ff_rl_speedhq = { | |||||
121, | 121, | ||||
121, | 121, | ||||
(const uint16_t (*)[])speedhq_vlc, | (const uint16_t (*)[])speedhq_vlc, | ||||
@@ -236,7 +236,7 @@ static inline int decode_dct_block(const SHQContext *s, GetBitContext *gb, int l | |||||
for ( ;; ) { | for ( ;; ) { | ||||
int level, run; | int level, run; | ||||
UPDATE_CACHE_LE(re, gb); | UPDATE_CACHE_LE(re, gb); | ||||
GET_RL_VLC(level, run, re, gb, rl_speedhq.rl_vlc[0], | |||||
GET_RL_VLC(level, run, re, gb, ff_rl_speedhq.rl_vlc[0], | |||||
TEX_VLC_BITS, 2, 0); | TEX_VLC_BITS, 2, 0); | ||||
if (level == 127) { | if (level == 127) { | ||||
break; | break; | ||||
@@ -570,8 +570,8 @@ static av_cold void speedhq_static_init(void) | |||||
ff_mpeg12_vlc_dc_chroma_code, 2, 2, | ff_mpeg12_vlc_dc_chroma_code, 2, 2, | ||||
INIT_VLC_OUTPUT_LE, 514); | INIT_VLC_OUTPUT_LE, 514); | ||||
ff_rl_init(&rl_speedhq, speedhq_static_rl_table_store); | |||||
INIT_2D_VLC_RL(rl_speedhq, 674, INIT_VLC_LE); | |||||
ff_rl_init(&ff_rl_speedhq, speedhq_static_rl_table_store); | |||||
INIT_2D_VLC_RL(ff_rl_speedhq, 674, INIT_VLC_LE); | |||||
compute_alpha_vlcs(); | compute_alpha_vlcs(); | ||||
} | } | ||||
@@ -0,0 +1,316 @@ | |||||
/* | |||||
* SpeedHQ encoder | |||||
* Copyright (c) 2000, 2001 Fabrice Bellard | |||||
* Copyright (c) 2003 Alex Beregszaszi | |||||
* Copyright (c) 2003-2004 Michael Niedermayer | |||||
* Copyright (c) 2020 FFmpeg | |||||
* | |||||
* This file is part of FFmpeg. | |||||
* | |||||
* FFmpeg 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. | |||||
* | |||||
* FFmpeg 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 | |||||
*/ | |||||
/** | |||||
* @file | |||||
* SpeedHQ encoder. | |||||
*/ | |||||
#include "libavutil/pixdesc.h" | |||||
#include "libavutil/thread.h" | |||||
#include "avcodec.h" | |||||
#include "mpeg12.h" | |||||
#include "mpegvideo.h" | |||||
#include "speedhqenc.h" | |||||
extern RLTable ff_rl_speedhq; | |||||
static uint8_t speedhq_static_rl_table_store[2][2*MAX_RUN + MAX_LEVEL + 3]; | |||||
static uint16_t mpeg12_vlc_dc_lum_code_reversed[12]; | |||||
static uint16_t mpeg12_vlc_dc_chroma_code_reversed[12]; | |||||
/* simple include everything table for dc, first byte is bits | |||||
* number next 3 are code */ | |||||
static uint32_t speedhq_lum_dc_uni[512]; | |||||
static uint32_t speedhq_chr_dc_uni[512]; | |||||
static uint8_t speedhq_index_run[2][64]; | |||||
static int8_t speedhq_max_level[2][64]; | |||||
static uint8_t uni_speedhq_ac_vlc_len[64 * 64 * 2]; | |||||
static uint32_t reverse(uint32_t num, int bits) | |||||
{ | |||||
return bitswap_32(num) >> (32 - bits); | |||||
} | |||||
static void reverse_code(const uint16_t *code, const uint8_t *bits, | |||||
uint16_t *reversed_code, int num_entries) | |||||
{ | |||||
for (int i = 0; i < num_entries; i++) | |||||
reversed_code[i] = reverse(code[i], bits[i]); | |||||
} | |||||
static av_cold void speedhq_init_static_data(void) | |||||
{ | |||||
/* Exactly the same as MPEG-2, except little-endian. */ | |||||
reverse_code(ff_mpeg12_vlc_dc_lum_code, | |||||
ff_mpeg12_vlc_dc_lum_bits, | |||||
mpeg12_vlc_dc_lum_code_reversed, | |||||
12); | |||||
reverse_code(ff_mpeg12_vlc_dc_chroma_code, | |||||
ff_mpeg12_vlc_dc_chroma_bits, | |||||
mpeg12_vlc_dc_chroma_code_reversed, | |||||
12); | |||||
ff_rl_init(&ff_rl_speedhq, speedhq_static_rl_table_store); | |||||
for (int i = 0; i < 64; i++) { | |||||
speedhq_max_level[0][i] = ff_rl_speedhq.max_level[0][i]; | |||||
speedhq_index_run[0][i] = ff_rl_speedhq.index_run[0][i]; | |||||
} | |||||
/* build unified dc encoding tables */ | |||||
for (int i = -255; i < 256; i++) { | |||||
int adiff, index; | |||||
int bits, code; | |||||
int diff = i; | |||||
adiff = FFABS(diff); | |||||
if (diff < 0) | |||||
diff--; | |||||
index = av_log2(2 * adiff); | |||||
bits = ff_mpeg12_vlc_dc_lum_bits[index] + index; | |||||
code = mpeg12_vlc_dc_lum_code_reversed[index] + | |||||
(av_mod_uintp2(diff, index) << ff_mpeg12_vlc_dc_lum_bits[index]); | |||||
speedhq_lum_dc_uni[i + 255] = bits + (code << 8); | |||||
bits = ff_mpeg12_vlc_dc_chroma_bits[index] + index; | |||||
code = mpeg12_vlc_dc_chroma_code_reversed[index] + | |||||
(av_mod_uintp2(diff, index) << ff_mpeg12_vlc_dc_chroma_bits[index]); | |||||
speedhq_chr_dc_uni[i + 255] = bits + (code << 8); | |||||
} | |||||
ff_init_uni_ac_vlc(&ff_rl_speedhq, uni_speedhq_ac_vlc_len); | |||||
} | |||||
av_cold int ff_speedhq_encode_init(MpegEncContext *s) | |||||
{ | |||||
static AVOnce init_static_once = AV_ONCE_INIT; | |||||
av_assert0(s->slice_context_count == 1); | |||||
if (s->width > 65500 || s->height > 65500) { | |||||
av_log(s, AV_LOG_ERROR, "SpeedHQ does not support resolutions above 65500x65500\n"); | |||||
return AVERROR(EINVAL); | |||||
} | |||||
s->min_qcoeff = -2048; | |||||
s->max_qcoeff = 2047; | |||||
ff_thread_once(&init_static_once, speedhq_init_static_data); | |||||
s->intra_ac_vlc_length = | |||||
s->intra_ac_vlc_last_length = | |||||
s->intra_chroma_ac_vlc_length = | |||||
s->intra_chroma_ac_vlc_last_length = uni_speedhq_ac_vlc_len; | |||||
switch (s->avctx->pix_fmt) { | |||||
case AV_PIX_FMT_YUV420P: | |||||
s->avctx->codec_tag = MKTAG('S','H','Q','0'); | |||||
break; | |||||
case AV_PIX_FMT_YUV422P: | |||||
s->avctx->codec_tag = MKTAG('S','H','Q','2'); | |||||
break; | |||||
case AV_PIX_FMT_YUV444P: | |||||
s->avctx->codec_tag = MKTAG('S','H','Q','4'); | |||||
break; | |||||
default: | |||||
av_assert0(0); | |||||
} | |||||
return 0; | |||||
} | |||||
void ff_speedhq_encode_picture_header(MpegEncContext *s) | |||||
{ | |||||
put_bits_le(&s->pb, 8, 100 - s->qscale * 2); /* FIXME why doubled */ | |||||
put_bits_le(&s->pb, 24, 4); /* no second field */ | |||||
/* length of first slice, will be filled out later */ | |||||
s->slice_start = 4; | |||||
put_bits_le(&s->pb, 24, 0); | |||||
} | |||||
void ff_speedhq_end_slice(MpegEncContext *s) | |||||
{ | |||||
int slice_len; | |||||
flush_put_bits_le(&s->pb); | |||||
slice_len = s->pb.buf_ptr - (s->pb.buf + s->slice_start); | |||||
AV_WL24(s->pb.buf + s->slice_start, slice_len); | |||||
/* length of next slice, will be filled out later */ | |||||
s->slice_start = s->pb.buf_ptr - s->pb.buf; | |||||
put_bits_le(&s->pb, 24, 0); | |||||
} | |||||
static inline void encode_dc(PutBitContext *pb, int diff, int component) | |||||
{ | |||||
unsigned int diff_u = diff + 255; | |||||
if (diff_u >= 511) { | |||||
int index; | |||||
if (diff < 0) { | |||||
index = av_log2_16bit(-2 * diff); | |||||
diff--; | |||||
} else { | |||||
index = av_log2_16bit(2 * diff); | |||||
} | |||||
if (component == 0) | |||||
put_bits_le(pb, | |||||
ff_mpeg12_vlc_dc_lum_bits[index] + index, | |||||
mpeg12_vlc_dc_lum_code_reversed[index] + | |||||
(av_mod_uintp2(diff, index) << ff_mpeg12_vlc_dc_lum_bits[index])); | |||||
else | |||||
put_bits_le(pb, | |||||
ff_mpeg12_vlc_dc_chroma_bits[index] + index, | |||||
mpeg12_vlc_dc_chroma_code_reversed[index] + | |||||
(av_mod_uintp2(diff, index) << ff_mpeg12_vlc_dc_chroma_bits[index])); | |||||
} else { | |||||
if (component == 0) | |||||
put_bits_le(pb, | |||||
speedhq_lum_dc_uni[diff + 255] & 0xFF, | |||||
speedhq_lum_dc_uni[diff + 255] >> 8); | |||||
else | |||||
put_bits_le(pb, | |||||
speedhq_chr_dc_uni[diff + 255] & 0xFF, | |||||
speedhq_chr_dc_uni[diff + 255] >> 8); | |||||
} | |||||
} | |||||
static void encode_block(MpegEncContext *s, int16_t *block, int n) | |||||
{ | |||||
int alevel, level, last_non_zero, dc, i, j, run, last_index, sign; | |||||
int code; | |||||
int component, val; | |||||
/* DC coef */ | |||||
component = (n <= 3 ? 0 : (n&1) + 1); | |||||
dc = block[0]; /* overflow is impossible */ | |||||
val = s->last_dc[component] - dc; /* opposite of most codecs */ | |||||
encode_dc(&s->pb, val, component); | |||||
s->last_dc[component] = dc; | |||||
/* now quantify & encode AC coefs */ | |||||
last_non_zero = 0; | |||||
last_index = s->block_last_index[n]; | |||||
for (i = 1; i <= last_index; i++) { | |||||
j = s->intra_scantable.permutated[i]; | |||||
level = block[j]; | |||||
/* encode using VLC */ | |||||
if (level != 0) { | |||||
run = i - last_non_zero - 1; | |||||
alevel = level; | |||||
MASK_ABS(sign, alevel); | |||||
sign &= 1; | |||||
if (alevel <= speedhq_max_level[0][run]) { | |||||
code = speedhq_index_run[0][run] + alevel - 1; | |||||
/* store the VLC & sign at once */ | |||||
put_bits_le(&s->pb, ff_rl_speedhq.table_vlc[code][1] + 1, | |||||
ff_rl_speedhq.table_vlc[code][0] + (sign << ff_rl_speedhq.table_vlc[code][1])); | |||||
} else { | |||||
/* escape seems to be pretty rare <5% so I do not optimize it */ | |||||
put_bits_le(&s->pb, ff_rl_speedhq.table_vlc[121][1], ff_rl_speedhq.table_vlc[121][0]); | |||||
/* escape: only clip in this case */ | |||||
put_bits_le(&s->pb, 6, run); | |||||
put_bits_le(&s->pb, 12, level + 2048); | |||||
} | |||||
last_non_zero = i; | |||||
} | |||||
} | |||||
/* end of block */ | |||||
put_bits_le(&s->pb, ff_rl_speedhq.table_vlc[122][1], ff_rl_speedhq.table_vlc[122][0]); | |||||
} | |||||
void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]) | |||||
{ | |||||
int i; | |||||
for(i=0;i<6;i++) { | |||||
encode_block(s, block[i], i); | |||||
} | |||||
if (s->chroma_format == CHROMA_444) { | |||||
encode_block(s, block[8], 8); | |||||
encode_block(s, block[9], 9); | |||||
encode_block(s, block[6], 6); | |||||
encode_block(s, block[7], 7); | |||||
encode_block(s, block[10], 10); | |||||
encode_block(s, block[11], 11); | |||||
} else if (s->chroma_format == CHROMA_422) { | |||||
encode_block(s, block[6], 6); | |||||
encode_block(s, block[7], 7); | |||||
} | |||||
s->i_tex_bits += get_bits_diff(s); | |||||
} | |||||
static int ff_speedhq_mb_rows_in_slice(int slice_num, int mb_height) | |||||
{ | |||||
return mb_height / 4 + (slice_num < (mb_height % 4)); | |||||
} | |||||
int ff_speedhq_mb_y_order_to_mb(int mb_y_order, int mb_height, int *first_in_slice) | |||||
{ | |||||
int slice_num = 0; | |||||
while (mb_y_order >= ff_speedhq_mb_rows_in_slice(slice_num, mb_height)) { | |||||
mb_y_order -= ff_speedhq_mb_rows_in_slice(slice_num, mb_height); | |||||
slice_num++; | |||||
} | |||||
*first_in_slice = (mb_y_order == 0); | |||||
return mb_y_order * 4 + slice_num; | |||||
} | |||||
#if CONFIG_SPEEDHQ_ENCODER | |||||
static const AVClass speedhq_class = { | |||||
.class_name = "speedhq encoder", | |||||
.item_name = av_default_item_name, | |||||
.option = ff_mpv_generic_options, | |||||
.version = LIBAVUTIL_VERSION_INT, | |||||
}; | |||||
AVCodec ff_speedhq_encoder = { | |||||
.name = "speedhq", | |||||
.long_name = NULL_IF_CONFIG_SMALL("NewTek SpeedHQ"), | |||||
.type = AVMEDIA_TYPE_VIDEO, | |||||
.id = AV_CODEC_ID_SPEEDHQ, | |||||
.priv_data_size = sizeof(MpegEncContext), | |||||
.init = ff_mpv_encode_init, | |||||
.encode2 = ff_mpv_encode_picture, | |||||
.close = ff_mpv_encode_end, | |||||
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP, | |||||
.pix_fmts = (const enum AVPixelFormat[]) { | |||||
AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, | |||||
AV_PIX_FMT_NONE | |||||
}, | |||||
.priv_class = &speedhq_class, | |||||
}; | |||||
#endif |
@@ -0,0 +1,48 @@ | |||||
/* | |||||
* SpeedHQ encoder | |||||
* Copyright (c) 2000, 2001 Fabrice Bellard | |||||
* Copyright (c) 2003 Alex Beregszaszi | |||||
* Copyright (c) 2003-2004 Michael Niedermayer | |||||
* | |||||
* This file is part of FFmpeg. | |||||
* | |||||
* FFmpeg 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. | |||||
* | |||||
* FFmpeg 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 | |||||
*/ | |||||
/** | |||||
* @file | |||||
* SpeedHQ encoder. | |||||
*/ | |||||
#ifndef AVCODEC_SPEEDHQENC_H | |||||
#define AVCODEC_SPEEDHQENC_H | |||||
#include <stdint.h> | |||||
#include "mjpeg.h" | |||||
#include "mjpegenc_common.h" | |||||
#include "mpegvideo.h" | |||||
#include "put_bits.h" | |||||
int ff_speedhq_encode_init(MpegEncContext *s); | |||||
void ff_speedhq_encode_close(MpegEncContext *s); | |||||
void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]); | |||||
void ff_speedhq_encode_picture_header(MpegEncContext *s); | |||||
void ff_speedhq_end_slice(MpegEncContext *s); | |||||
int ff_speedhq_mb_y_order_to_mb(int mb_y_order, int mb_height, int *first_in_slice); | |||||
#endif /* AVCODEC_SPEEDHQENC_H */ |
@@ -28,8 +28,8 @@ | |||||
#include "libavutil/version.h" | #include "libavutil/version.h" | ||||
#define LIBAVCODEC_VERSION_MAJOR 58 | #define LIBAVCODEC_VERSION_MAJOR 58 | ||||
#define LIBAVCODEC_VERSION_MINOR 112 | |||||
#define LIBAVCODEC_VERSION_MICRO 103 | |||||
#define LIBAVCODEC_VERSION_MINOR 113 | |||||
#define LIBAVCODEC_VERSION_MICRO 100 | |||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | ||||
LIBAVCODEC_VERSION_MINOR, \ | LIBAVCODEC_VERSION_MINOR, \ | ||||