[FFmpeg-devel] [PATCH 2/2] SpeedHQ encoder
Jean-Baptiste Kempf
jb at videolan.org
Mon Jul 13 14:16:19 EEST 2020
This is heavily based on MPEG-2 encoder, of course.
---
Changelog | 1 +
doc/general.texi | 2 +-
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/mpegutils.h | 1 +
libavcodec/mpegvideo.h | 3 +++
libavcodec/mpegvideo_enc.c | 52 +++++++++++++++++++++++++++++++++++---
libavcodec/version.h | 2 +-
8 files changed, 58 insertions(+), 5 deletions(-)
diff --git a/Changelog b/Changelog
index 49fc260458..8f3dcbec87 100644
--- a/Changelog
+++ b/Changelog
@@ -7,6 +7,7 @@ version <next>:
- PGX decoder
- chromanr video filter
- VDPAU accelerated HEVC 10/12bit decoding
+- SpeedHQ encoder
version 4.3:
diff --git a/doc/general.texi b/doc/general.texi
index 53d556c56c..7ab1c61267 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -971,7 +971,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 2 @tab X @tab X
@item MPEG-4 part 2 Microsoft variant version 3 @tab X @tab X
- at item Newtek SpeedHQ @tab @tab X
+ at item Newtek SpeedHQ @tab X @tab X
@item Nintendo Gamecube THP video @tab @tab X
@item NotchLC @tab @tab X
@item NuppelVideo/RTjpeg @tab @tab X
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 18353da549..52445130f4 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -614,6 +614,7 @@ OBJS-$(CONFIG_SONIC_DECODER) += sonic.o
OBJS-$(CONFIG_SONIC_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_ENCODER) += speedhq.o mpeg12data.o speedhqenc.o
OBJS-$(CONFIG_SP5X_DECODER) += sp5xdec.o
OBJS-$(CONFIG_SRGC_DECODER) += mscc.o
OBJS-$(CONFIG_SRT_DECODER) += srtdec.o ass.o htmlsubtitles.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index a5048290f7..b542910303 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -290,6 +290,7 @@ extern AVCodec ff_snow_encoder;
extern AVCodec ff_snow_decoder;
extern AVCodec ff_sp5x_decoder;
extern AVCodec ff_speedhq_decoder;
+extern AVCodec ff_speedhq_encoder;
extern AVCodec ff_srgc_decoder;
extern AVCodec ff_sunrast_encoder;
extern AVCodec ff_sunrast_decoder;
diff --git a/libavcodec/mpegutils.h b/libavcodec/mpegutils.h
index 1ed21c19be..81f0b73bb1 100644
--- a/libavcodec/mpegutils.h
+++ b/libavcodec/mpegutils.h
@@ -125,6 +125,7 @@ enum OutputFormat {
FMT_H261,
FMT_H263,
FMT_MJPEG,
+ FMT_SPEEDHQ,
};
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index 29e692f245..974c71b6bd 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -444,6 +444,9 @@ typedef struct MpegEncContext {
int inter_intra_pred;
int mspel;
+ /* SpeedHQ specific */
+ int slice_start;
+
/* decompression specific */
GetBitContext gb;
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index c3ef40556a..221079452c 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -51,6 +51,7 @@
#include "mathops.h"
#include "mpegutils.h"
#include "mjpegenc.h"
+#include "speedhqenc.h"
#include "msmpeg4.h"
#include "pixblockdsp.h"
#include "qpeldsp.h"
@@ -326,6 +327,15 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx)
return AVERROR(EINVAL);
}
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:
if (avctx->pix_fmt != AV_PIX_FMT_YUV420P) {
av_log(avctx, AV_LOG_ERROR, "only YUV420 is supported\n");
@@ -732,7 +742,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
//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
s->intra_quant_bias = 3 << (QUANT_BIAS_SHIFT - 3);
s->inter_quant_bias = 0;
@@ -783,6 +793,16 @@ FF_ENABLE_DEPRECATION_WARNINGS
avctx->delay = 0;
s->low_delay = 1;
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:
if (!CONFIG_H261_ENCODER)
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) {
s->intra_matrix[j] =
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 {
/* MPEG-1/2 */
s->chroma_intra_matrix[j] =
@@ -2562,6 +2585,10 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s,
if (CONFIG_MJPEG_ENCODER)
ff_mjpeg_encode_mb(s, s->block);
break;
+ case AV_CODEC_ID_SPEEDHQ:
+ if (CONFIG_SPEEDHQ_ENCODER)
+ ff_speedhq_encode_mb(s, s->block);
+ break;
default:
av_assert1(0);
}
@@ -2816,6 +2843,8 @@ static void write_slice_end(MpegEncContext *s){
ff_mpeg4_stuffing(&s->pb);
}else if(CONFIG_MJPEG_ENCODER && s->out_format == FMT_MJPEG){
ff_mjpeg_encode_stuffing(s);
+ }else if(CONFIG_SPEEDHQ_ENCODER && s->out_format == FMT_SPEEDHQ){
+ ff_speedhq_end_slice(s);
}
avpriv_align_put_bits(&s->pb);
@@ -2906,7 +2935,7 @@ int ff_mpv_reallocate_putbitbuffer(MpegEncContext *s, size_t threshold, size_t s
static int encode_thread(AVCodecContext *c, 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 i, j;
MpegEncContext best_s = { 0 }, backup_s;
@@ -2967,7 +2996,16 @@ static int encode_thread(AVCodecContext *c, void *arg){
s->resync_mb_y=0;
s->first_slice_line = 1;
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_y= mb_y;
@@ -3855,6 +3893,10 @@ static int encode_picture(MpegEncContext *s, int picture_number)
s->chroma_intra_matrix, s->intra_quant_bias, 8, 8, 1);
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
s->current_picture_ptr->f->key_frame =
@@ -3873,6 +3915,10 @@ static int encode_picture(MpegEncContext *s, int picture_number)
ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable,
s->pred, s->intra_matrix, s->chroma_intra_matrix);
break;
+ case FMT_SPEEDHQ:
+ if (CONFIG_SPEEDHQ_ENCODER)
+ ff_speedhq_encode_picture_header(s);
+ break;
case FMT_H261:
if (CONFIG_H261_ENCODER)
ff_h261_encode_picture_header(s, picture_number);
diff --git a/libavcodec/version.h b/libavcodec/version.h
index e75891d463..3e34af5348 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,7 +29,7 @@
#define LIBAVCODEC_VERSION_MAJOR 58
#define LIBAVCODEC_VERSION_MINOR 95
-#define LIBAVCODEC_VERSION_MICRO 100
+#define LIBAVCODEC_VERSION_MICRO 101
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
--
2.27.0
More information about the ffmpeg-devel
mailing list