Libavcodec: added HuffYUV and FFV1

This commit is contained in:
Martin Pulec
2018-09-24 15:20:58 +02:00
parent a5c4ad8f63
commit 3f8d00391f
5 changed files with 68 additions and 13 deletions

View File

@@ -6,6 +6,7 @@
#include "debug.h"
#include "host.h"
#include "types.h"
#ifndef LIBAVCODEC_COMMON_H_
#define LIBAVCODEC_COMMON_H_
@@ -184,6 +185,12 @@ static void print_libav_error(int verbosity, const char *msg, int rc) {
log_msg(verbosity, "%s: %s\n", msg, errbuf);
}
static bool libav_codec_has_extradata(codec_t codec) {
if (codec == HFYU || codec == FFV1) {
return true;
}
return false;
}
#endif // LIBAVCODEC_COMMON_H_

View File

@@ -89,6 +89,8 @@ typedef enum {
J2K, ///< JPEG 2000
J2KR, ///< JPEG 2000 RGB
HW_VDPAU, ///< VDPAU hardware surface
HFYU, ///< HuffYUV
FFV1, ///< FFV1
VIDEO_CODEC_COUNT ///< count of known video codecs (including VIDEO_CODEC_NONE)
} codec_t;

View File

@@ -170,8 +170,12 @@ static const struct codec_info_t codec_info[] = {
#ifdef HWACC_VDPAU
[HW_VDPAU] = {"HW_VDPAU", "VDPAU hardware surface",
to_fourcc('V', 'D', 'P', 'S'), 0, 1.0, 8, sizeof(hw_vdpau_frame), FALSE, TRUE, FALSE, TRUE, "vdpau"}
to_fourcc('V', 'D', 'P', 'S'), 0, 1.0, 8, sizeof(hw_vdpau_frame), FALSE, TRUE, FALSE, TRUE, "vdpau"},
#endif
[HFYU] = {"HFYU", "HuffYUV",
to_fourcc('H','F','Y','U'), 0, 1.0, 8, 0, FALSE, TRUE, FALSE, FALSE, "hfyu"},
[FFV1] = {"FFV1", "FFV1",
to_fourcc('F','F','V','1'), 0, 1.0, 8, 0, FALSE, TRUE, FALSE, FALSE, "ffv1"},
};
/**

View File

@@ -165,6 +165,20 @@ static unordered_map<codec_t, codec_params_t, hash<int>> codec_params = {
nullptr,
setparam_vp8_vp9,
}},
{ HFYU, codec_params_t{
AV_CODEC_ID_HUFFYUV,
nullptr,
0,
nullptr,
setparam_default
}},
{ FFV1, codec_params_t{
AV_CODEC_ID_FFV1,
nullptr,
0,
nullptr,
setparam_default
}},
};
codec_t get_ug_for_av_codec(AVCodecID id) {
@@ -1418,6 +1432,12 @@ static shared_ptr<video_frame> libavcodec_compress_tile(struct module *mod, shar
/* encode the image */
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 100)
out->tiles[0].data_len = 0;
if (libav_codec_has_extradata(s->out_codec)) { // we need to store extradata for HuffYUV/FFV1 in the beginning
out->tiles[0].data_len += sizeof(uint32_t) + s->codec_ctx->extradata_size;
*(uint32_t *) out->tiles[0].data = s->codec_ctx->extradata_size;
memcpy(out->tiles[0].data + sizeof(uint32_t), s->codec_ctx->extradata, s->codec_ctx->extradata_size);
}
ret = avcodec_send_frame(s->codec_ctx, frame);
if (ret == 0) {
AVPacket pkt;

View File

@@ -89,11 +89,10 @@ struct state_libavcodec_decompress {
AVFrame *frame;
AVPacket pkt;
int width, height;
struct video_desc desc;
int pitch;
int rshift, gshift, bshift;
int max_compressed_len;
codec_t in_codec;
codec_t out_codec;
unsigned last_frame_seq:22; // This gives last sucessfully decoded frame seq number. It is the buffer number from the packet format header, uses 22 bits.
@@ -214,6 +213,8 @@ static const struct decoder_info decoders[] = {
{ J2K, AV_CODEC_ID_JPEG2000, NULL, { NULL } },
{ VP8, AV_CODEC_ID_VP8, NULL, { NULL } },
{ VP9, AV_CODEC_ID_VP9, NULL, { NULL } },
{ HFYU, AV_CODEC_ID_HUFFYUV, NULL, { NULL } },
{ FFV1, AV_CODEC_ID_FFV1, NULL, { NULL } },
};
ADD_TO_PARAM(force_lavd_decoder, "force-lavd-decoder", "* force-lavd-decoder=<decoder>[:<decoder2>...]\n"
@@ -224,7 +225,7 @@ ADD_TO_PARAM(force_hw_accel, "use-hw-accel", "* use-hw-accel\n"
" Tries to use hardware acceleration. \n");
#endif
static bool configure_with(struct state_libavcodec_decompress *s,
struct video_desc desc)
struct video_desc desc, void *extradata, int extradata_size)
{
const struct decoder_info *dec = NULL;
@@ -299,6 +300,13 @@ static bool configure_with(struct state_libavcodec_decompress *s,
log_msg(LOG_LEVEL_ERROR, "[lavd] Unable to allocate codec context.\n");
return false;
}
if (extradata) {
s->codec_ctx->extradata = malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
memcpy(s->codec_ctx->extradata, extradata, extradata_size);
s->codec_ctx->extradata_size = extradata_size;
}
s->codec_ctx->width = desc.width;
s->codec_ctx->height = desc.height;
set_codec_context_params(s);
pthread_mutex_lock(s->global_lavcd_lock);
if (avcodec_open2(s->codec_ctx, *codec_it, NULL) < 0) {
@@ -352,7 +360,6 @@ static void * libavcodec_decompress_init(void)
avcodec_register_all();
#endif
s->width = s->height = s->pitch = 0;
s->codec_ctx = NULL;
s->frame = NULL;
av_init_packet(&s->pkt);
@@ -384,13 +391,17 @@ static int libavcodec_decompress_reconfigure(void *state, struct video_desc desc
s->rshift = rshift;
s->gshift = gshift;
s->bshift = bshift;
s->in_codec = desc.color_spec;
s->out_codec = out_codec;
s->width = desc.width;
s->height = desc.height;
s->desc = desc;
deconfigure(s);
return configure_with(s, desc);
if (libav_codec_has_extradata(desc.color_spec)) {
// for codecs that have metadata we have to defer initialization
// because we don't have the data right now
return TRUE;
} else {
return configure_with(s, desc, NULL, 0);
}
}
static void nv12_to_yuv422(char *dst_buffer, AVFrame *in_frame,
@@ -1272,6 +1283,15 @@ static decompress_status libavcodec_decompress(void *state, unsigned char *dst,
int len, got_frame = 0;
decompress_status res = DECODER_NO_FRAME;
if (libav_codec_has_extradata(s->desc.color_spec)) {
int extradata_size = *(uint32_t *) src;
if (s->codec_ctx == NULL) {
configure_with(s, s->desc, src + sizeof(uint32_t), extradata_size);
}
src += extradata_size + sizeof(uint32_t);
src_len -= extradata_size + sizeof(uint32_t);
}
s->pkt.size = src_len;
s->pkt.data = src;
@@ -1305,9 +1325,9 @@ static decompress_status libavcodec_decompress(void *state, unsigned char *dst,
* decompression went good even with the reported error.
*/
if (len < 0) {
if (s->in_codec == JPEG) {
if (s->desc.color_spec == JPEG) {
log_msg(LOG_LEVEL_WARNING, "[lavd] Perhaps JPEG restart interval >0 set? (Not supported by lavd, try '-c JPEG:90:0' on sender).\n");
} else if (s->in_codec == MJPG) {
} else if (s->desc.color_spec == MJPG) {
log_msg(LOG_LEVEL_WARNING, "[lavd] Perhaps old libavcodec without slices support? (Try '-c libavcodec:codec=MJPEG:threads=no' on sender).\n");
#if LIBAVCODEC_VERSION_MAJOR <= 54 // Libav with libavcodec 54 will crash otherwise
return DECODER_NO_FRAME;
@@ -1325,7 +1345,7 @@ static decompress_status libavcodec_decompress(void *state, unsigned char *dst,
/* Skip the frame if this is not an I-frame
* and we have missed some of previous frames for VP8 because the
* decoder makes ugly artifacts. We rather wait for next I-frame. */
if (s->in_codec == VP8 &&
if (s->desc.color_spec == VP8 &&
(s->frame->pict_type != AV_PICTURE_TYPE_I &&
(!s->last_frame_seq_initialized || (s->last_frame_seq + 1) % ((1<<22) - 1) != frame_seq))) {
log_msg(LOG_LEVEL_WARNING, "[lavd] Missing appropriate I-frame "
@@ -1340,7 +1360,7 @@ static decompress_status libavcodec_decompress(void *state, unsigned char *dst,
}
#endif
bool ret = change_pixfmt(s->frame, dst, s->frame->format,
s->out_codec, s->width, s->height, s->pitch);
s->out_codec, s->desc.width, s->desc.height, s->pitch);
if(ret == TRUE) {
s->last_frame_seq_initialized = true;
s->last_frame_seq = frame_seq;
@@ -1426,6 +1446,8 @@ static const struct decode_from_to *libavcodec_decompress_get_decoders() {
{ J2K, RGB, 500 },
{ VP8, UYVY, 500 },
{ VP9, UYVY, 500 },
{ HFYU, UYVY, 500 },
{ FFV1, UYVY, 500 },
};
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;