diff mbox series

[FFmpeg-devel,2/2] SpeedHQ encoder

Message ID 20200713111619.226490-2-jb@videolan.org
State Superseded
Headers show
Series [FFmpeg-devel,1/2] mpeg2: Renaming functions around init_uni_ac_vlc
Related show

Checks

Context Check Description
andriy/default pending
andriy/make fail Make failed

Commit Message

Jean-Baptiste Kempf July 13, 2020, 11:16 a.m. UTC
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 mbox series

Patch

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
-@item Newtek SpeedHQ               @tab     @tab  X
+@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, \