Commit 064698d3 authored by Guillaume Martres's avatar Guillaume Martres Committed by Anton Khirnov

Add HEVC decoder

Initially written by Guillaume Martres <smarter@ubuntu.com> as a GSoC
project. Further contributions by the OpenHEVC project and other
developers, namely:

Mickaël Raulet <mraulet@insa-rennes.fr>
Seppo Tomperi <seppo.tomperi@vtt.fi>
Gildas Cocherel <gildas.cocherel@laposte.net>
Khaled Jerbi <khaled_jerbi@yahoo.fr>
Wassim Hamidouche <wassim.hamidouche@insa-rennes.fr>
Vittorio Giovara <vittorio.giovara@gmail.com>
Jan Ekström <jeebjp@gmail.com>
Anton Khirnov <anton@khirnov.net>
Martin Storsjö <martin@martin.st>
Luca Barbato <lu_zero@gentoo.org>
Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
Reimar Döffinger <Reimar.Doeffinger@gmx.de>
Diego Biurrun <diego@biurrun.de>
Signed-off-by: 's avatarAnton Khirnov <anton@khirnov.net>
parent 0a9e94bb
......@@ -41,6 +41,7 @@ version 10:
- Enhanced Low Delay AAC (ER AAC ELD) decoding (no LD SBR support)
- F4V muxer
- HNM version 4 demuxer and video decoder
- HEVC decoder
version 9:
......
......@@ -1599,6 +1599,7 @@ h263i_decoder_select="h263_decoder"
h263p_encoder_select="h263_encoder"
h264_decoder_select="golomb h264chroma h264dsp h264pred h264qpel videodsp"
h264_decoder_suggest="error_resilience"
hevc_decoder_select="dsputil golomb videodsp"
huffyuv_decoder_select="dsputil"
huffyuv_encoder_select="dsputil huffman"
iac_decoder_select="dsputil fft mdct sinewin"
......
......@@ -526,6 +526,7 @@ following image formats are supported:
@item H.263+ / H.263-1998 / H.263 version 2 @tab X @tab X
@item H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 @tab E @tab X
@tab encoding supported through external library libx264
@item HEVC @tab @tab X
@item HNM version 4 @tab @tab X
@item HuffYUV @tab X @tab X
@item HuffYUV FFmpeg variant @tab X @tab X
......
......@@ -196,6 +196,9 @@ OBJS-$(CONFIG_H264_DECODER) += h264.o \
h264_loopfilter.o h264_direct.o \
cabac.o h264_sei.o h264_ps.o \
h264_refs.o h264_cavlc.o h264_cabac.o
OBJS-$(CONFIG_HEVC_DECODER) += hevc.o hevc_mvs.o hevc_ps.o hevc_sei.o \
hevc_cabac.o hevc_refs.o hevcpred.o \
hevcdsp.o hevc_filter.o cabac.o
OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o
OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o huffyuvdec.o
OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o huffyuvenc.o
......@@ -635,6 +638,7 @@ OBJS-$(CONFIG_H264_PARSER) += h264_parser.o h264.o \
h264_refs.o h264_sei.o h264_direct.o \
h264_loopfilter.o h264_cabac.o \
h264_cavlc.o h264_ps.o
OBJS-$(CONFIG_HEVC_PARSER) += hevc_parser.o
OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg_parser.o
OBJS-$(CONFIG_MLP_PARSER) += mlp_parser.o mlp.o
OBJS-$(CONFIG_MPEG4VIDEO_PARSER) += mpeg4video_parser.o h263.o \
......
......@@ -153,6 +153,7 @@ void avcodec_register_all(void)
REGISTER_DECODER(H263I, h263i);
REGISTER_ENCODER(H263P, h263p);
REGISTER_DECODER(H264, h264);
REGISTER_DECODER(HEVC, hevc);
REGISTER_DECODER(HNM4_VIDEO, hnm4_video);
REGISTER_ENCDEC (HUFFYUV, huffyuv);
REGISTER_DECODER(IDCIN, idcin);
......@@ -453,6 +454,7 @@ void avcodec_register_all(void)
REGISTER_PARSER(H261, h261);
REGISTER_PARSER(H263, h263);
REGISTER_PARSER(H264, h264);
REGISTER_PARSER(HEVC, hevc);
REGISTER_PARSER(MJPEG, mjpeg);
REGISTER_PARSER(MLP, mlp);
REGISTER_PARSER(MPEG4VIDEO, mpeg4video);
......
......@@ -275,6 +275,7 @@ enum AVCodecID {
AV_CODEC_ID_G2M,
AV_CODEC_ID_WEBP,
AV_CODEC_ID_HNM4_VIDEO,
AV_CODEC_ID_HEVC,
/* various PCM "codecs" */
AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs
......
......@@ -162,4 +162,24 @@ static int av_unused get_cabac_terminate(CABACContext *c){
}
}
/**
* Skip @p n bytes and reset the decoder.
* @return the address of the first skipped byte or NULL if there's less than @p n bytes left
*/
static av_unused const uint8_t* skip_bytes(CABACContext *c, int n) {
const uint8_t *ptr = c->bytestream;
if (c->low & 0x1)
ptr--;
#if CABAC_BITS == 16
if (c->low & 0x1FF)
ptr--;
#endif
if ((int) (c->bytestream_end - ptr) < n)
return NULL;
ff_init_cabac_decoder(c, ptr + n, c->bytestream_end - ptr - n);
return ptr;
}
#endif /* AVCODEC_CABAC_FUNCTIONS_H */
......@@ -1243,6 +1243,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.long_name = NULL_IF_CONFIG_SMALL("HNM 4 video"),
.props = AV_CODEC_PROP_LOSSY,
},
{
.id = AV_CODEC_ID_HEVC,
.type = AVMEDIA_TYPE_VIDEO,
.name = "hevc",
.long_name = NULL_IF_CONFIG_SMALL("HEVC (High Efficiency Video Coding)"),
.props = AV_CODEC_PROP_LOSSY,
},
/* various PCM "codecs" */
{
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* HEVC Annex B format parser
*
* Copyright (C) 2012 - 2013 Guillaume Martres
*
* This file is part of Libav.
*
* Libav 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.
*
* Libav 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 Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/common.h"
#include "parser.h"
#include "hevc.h"
#define START_CODE 0x000001 ///< start_code_prefix_one_3bytes
/**
* Find the end of the current frame in the bitstream.
* @return the position of the first byte of the next frame, or END_NOT_FOUND
*/
static int hevc_find_frame_end(AVCodecParserContext *s, const uint8_t *buf,
int buf_size)
{
int i;
ParseContext *pc = s->priv_data;
for (i = 0; i < buf_size; i++) {
int nut;
pc->state64 = (pc->state64 << 8) | buf[i];
if (((pc->state64 >> 3 * 8) & 0xFFFFFF) != START_CODE)
continue;
nut = (pc->state64 >> 2 * 8 + 1) & 0x3F;
// Beginning of access unit
if ((nut >= NAL_VPS && nut <= NAL_AUD) || nut == NAL_SEI_PREFIX ||
(nut >= 41 && nut <= 44) || (nut >= 48 && nut <= 55)) {
if (pc->frame_start_found) {
pc->frame_start_found = 0;
return i - 5;
}
} else if (nut <= NAL_RASL_R ||
(nut >= NAL_BLA_W_LP && nut <= NAL_CRA_NUT)) {
int first_slice_segment_in_pic_flag = buf[i] >> 7;
if (first_slice_segment_in_pic_flag) {
if (!pc->frame_start_found) {
pc->frame_start_found = 1;
s->key_frame = nut >= NAL_BLA_W_LP && nut <= NAL_CRA_NUT;
} else { // First slice of next frame found
pc->frame_start_found = 0;
return i - 5;
}
}
}
}
return END_NOT_FOUND;
}
static int hevc_parse(AVCodecParserContext *s, AVCodecContext *avctx,
const uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size)
{
int next;
ParseContext *pc = s->priv_data;
if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
next = buf_size;
} else {
next = hevc_find_frame_end(s, buf, buf_size);
if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
*poutbuf = NULL;
*poutbuf_size = 0;
return buf_size;
}
}
*poutbuf = buf;
*poutbuf_size = buf_size;
return next;
}
// Split after the parameter sets at the beginning of the stream if they exist.
static int hevc_split(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
{
int i;
uint32_t state = -1;
int has_ps = 0;
for (i = 0; i < buf_size; i++) {
state = (state << 8) | buf[i];
if (((state >> 8) & 0xFFFFFF) == START_CODE) {
int nut = (state >> 1) & 0x3F;
if (nut >= NAL_VPS && nut <= NAL_PPS)
has_ps = 1;
else if (has_ps)
return i - 3;
else // no parameter set at the beginning of the stream
return 0;
}
}
return 0;
}
AVCodecParser ff_hevc_parser = {
.codec_ids = { AV_CODEC_ID_HEVC },
.priv_data_size = sizeof(ParseContext),
.parser_parse = hevc_parse,
.parser_close = ff_parse_close,
.split = hevc_split,
};
This diff is collapsed.
This diff is collapsed.
/*
* HEVC Supplementary Enhancement Information messages
*
* Copyright (C) 2012 - 2013 Guillaume Martres
* Copyright (C) 2012 - 2013 Gildas Cocherel
* Copyright (C) 2013 Vittorio Giovara
*
* This file is part of Libav.
*
* Libav 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.
*
* Libav 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 Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "golomb.h"
#include "hevc.h"
static void decode_nal_sei_decoded_picture_hash(HEVCContext *s,
int payload_size)
{
int cIdx, i;
GetBitContext *gb = &s->HEVClc.gb;
uint8_t hash_type = get_bits(gb, 8);
for (cIdx = 0; cIdx < 3; cIdx++) {
if (hash_type == 0) {
s->is_md5 = 1;
for (i = 0; i < 16; i++)
s->md5[cIdx][i] = get_bits(gb, 8);
} else if (hash_type == 1) {
// picture_crc = get_bits(gb, 16);
skip_bits(gb, 16);
} else if (hash_type == 2) {
// picture_checksum = get_bits(gb, 32);
skip_bits(gb, 32);
}
}
}
static void decode_nal_sei_frame_packing_arrangement(HEVCLocalContext *lc)
{
GetBitContext *gb = &lc->gb;
int cancel, type, quincunx;
get_ue_golomb(gb); // frame_packing_arrangement_id
cancel = get_bits1(gb); // frame_packing_cancel_flag
if (cancel == 0) {
type = get_bits(gb, 7); // frame_packing_arrangement_type
quincunx = get_bits1(gb); // quincunx_sampling_flag
skip_bits(gb, 6); // content_interpretation_type
// the following skips spatial_flipping_flag frame0_flipped_flag
// field_views_flag current_frame_is_frame0_flag
// frame0_self_contained_flag frame1_self_contained_flag
skip_bits(gb, 6);
if (quincunx == 0 && type != 5)
skip_bits(gb, 16); // frame[01]_grid_position_[xy]
skip_bits(gb, 8); // frame_packing_arrangement_reserved_byte
skip_bits1(gb); // frame_packing_arrangement_persistance_flag
}
skip_bits1(gb); // upsampled_aspect_ratio_flag
}
static int decode_nal_sei_message(HEVCContext *s)
{
GetBitContext *gb = &s->HEVClc.gb;
int payload_type = 0;
int payload_size = 0;
int byte = 0xFF;
av_log(s->avctx, AV_LOG_DEBUG, "Decoding SEI\n");
while (byte == 0xFF) {
byte = get_bits(gb, 8);
payload_type += byte;
}
byte = 0xFF;
while (byte == 0xFF) {
byte = get_bits(gb, 8);
payload_size += byte;
}
if (s->nal_unit_type == NAL_SEI_PREFIX) {
if (payload_type == 256)
decode_nal_sei_decoded_picture_hash(s, payload_size);
else if (payload_type == 45)
decode_nal_sei_frame_packing_arrangement(&s->HEVClc);
else {
av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", payload_type);
skip_bits(gb, 8 * payload_size);
}
} else { /* nal_unit_type == NAL_SEI_SUFFIX */
if (payload_type == 132)
decode_nal_sei_decoded_picture_hash(s, payload_size);
else {
av_log(s->avctx, AV_LOG_DEBUG, "Skipped SUFFIX SEI %d\n", payload_type);
skip_bits(gb, 8 * payload_size);
}
}
return 0;
}
static int more_rbsp_data(GetBitContext *gb)
{
return get_bits_left(gb) > 0 && show_bits(gb, 8) != 0x80;
}
int ff_hevc_decode_nal_sei(HEVCContext *s)
{
do {
decode_nal_sei_message(s);
} while (more_rbsp_data(&s->HEVClc.gb));
return 0;
}
This diff is collapsed.
This diff is collapsed.
/*
* HEVC video decoder
*
* Copyright (C) 2012 - 2013 Guillaume Martres
*
* This file is part of Libav.
*
* Libav 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.
*
* Libav 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 Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "hevc.h"
#define BIT_DEPTH 8
#include "hevcpred_template.c"
#undef BIT_DEPTH
#define BIT_DEPTH 9
#include "hevcpred_template.c"
#undef BIT_DEPTH
#define BIT_DEPTH 10
#include "hevcpred_template.c"
#undef BIT_DEPTH
void ff_hevc_pred_init(HEVCPredContext *hpc, int bit_depth)
{
#undef FUNC
#define FUNC(a, depth) a ## _ ## depth
#define HEVC_PRED(depth) \
hpc->intra_pred = FUNC(intra_pred, depth); \
hpc->pred_planar[0] = FUNC(pred_planar_0, depth); \
hpc->pred_planar[1] = FUNC(pred_planar_1, depth); \
hpc->pred_planar[2] = FUNC(pred_planar_2, depth); \
hpc->pred_planar[3] = FUNC(pred_planar_3, depth); \
hpc->pred_dc = FUNC(pred_dc, depth); \
hpc->pred_angular[0] = FUNC(pred_angular_0, depth); \
hpc->pred_angular[1] = FUNC(pred_angular_1, depth); \
hpc->pred_angular[2] = FUNC(pred_angular_2, depth); \
hpc->pred_angular[3] = FUNC(pred_angular_3, depth);
switch (bit_depth) {
case 9:
HEVC_PRED(9);
break;
case 10:
HEVC_PRED(10);
break;
default:
HEVC_PRED(8);
break;
}
}
This diff is collapsed.
......@@ -27,7 +27,7 @@
*/
#define LIBAVCODEC_VERSION_MAJOR 55
#define LIBAVCODEC_VERSION_MINOR 23
#define LIBAVCODEC_VERSION_MINOR 24
#define LIBAVCODEC_VERSION_MICRO 0
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment