codecparsers: Add VP9 codec parser

https://bugzilla.gnome.org/show_bug.cgi?id=757597
This commit is contained in:
Sreerenj Balachandran 2015-12-30 11:19:33 +02:00
parent 4717b48a03
commit b245e0f16c
8 changed files with 1726 additions and 3 deletions

View file

@ -5,7 +5,8 @@ libgstcodecparsers_@GST_API_VERSION@_la_SOURCES = \
gsth265parser.c gstvp8parser.c gstvp8rangedecoder.c \
parserutils.c nalutils.c dboolhuff.c vp8utils.c \
gstjpegparser.c \
gstmpegvideometa.c
gstmpegvideometa.c \
gstvp9parser.c vp9utils.c
libgstcodecparsers_@GST_API_VERSION@includedir = \
$(includedir)/gstreamer-@GST_API_VERSION@/gst/codecparsers
@ -16,7 +17,8 @@ libgstcodecparsers_@GST_API_VERSION@include_HEADERS = \
gstmpegvideoparser.h gsth264parser.h gstvc1parser.h gstmpeg4parser.h \
gsth265parser.h gstvp8parser.h gstvp8rangedecoder.h \
gstjpegparser.h \
gstmpegvideometa.h
gstmpegvideometa.h \
gstvp9parser.h vp9utils.h
libgstcodecparsers_@GST_API_VERSION@_la_CFLAGS = \
$(GST_PLUGINS_BAD_CFLAGS) \
@ -36,4 +38,5 @@ libgstcodecparsers_@GST_API_VERSION@_la_LDFLAGS = \
$(GST_ALL_LDFLAGS) \
$(GST_LT_LDFLAGS)
EXTRA_DIST = dboolhuff.LICENSE dboolhuff.PATENTS dboolhuff.AUTHORS
EXTRA_DIST = dboolhuff.LICENSE dboolhuff.PATENTS dboolhuff.AUTHORS \
vp9utils.LICENSE vp9utils.PATENTS vp9utils.AUTHORS

View file

@ -0,0 +1,815 @@
/* gstvp9parser.c
*
* Copyright (C) 2013-2014 Intel Corporation
* Copyright (C) 2015 Intel Corporation
* Author: XuGuangxin<Guangxin.Xu@intel.com>
* Author: Sreerenj Balachandran<sreerenj.balachandran@intel.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/**
* SECTION:gstvp9parser
* @short_description: Convenience library for parsing vp9 video bitstream.
*
* For more details about the structures, you can refer to the
* specifications:
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <stdlib.h>
#include <gst/base/gstbitreader.h>
#include "vp9utils.h"
#include "gstvp9parser.h"
#define MIN_TILE_WIDTH_B64 4
#define MAX_TILE_WIDTH_B64 64
/* order of sb64, where sb64 = 64x64 */
#define ALIGN_SB64(w) ((w + 63) >> 6)
GST_DEBUG_CATEGORY (gst_vp9_parser_debug);
#define GST_CAT_DEFAULT gst_vp9_parser_debug
static gboolean initialized = FALSE;
#define INITIALIZE_DEBUG_CATEGORY \
if (!initialized) { \
GST_DEBUG_CATEGORY_INIT (gst_vp9_parser_debug, "codecparsers_vp9", 0, \
"vp9 parser library"); \
initialized = TRUE; \
}
#define gst_vp9_read_bit(br) gst_bit_reader_get_bits_uint8_unchecked(br, 1)
#define gst_vp9_read_bits(br, bits) gst_bit_reader_get_bits_uint32_unchecked(br, bits)
#define GST_VP9_PARSER_GET_PRIVATE(parser) ((GstVp9ParserPrivate *)(parser->priv))
typedef struct _ReferenceSize
{
guint32 width;
guint32 height;
} ReferenceSize;
typedef struct
{
/* for loop filters */
gint8 ref_deltas[GST_VP9_MAX_REF_LF_DELTAS];
gint8 mode_deltas[GST_VP9_MAX_MODE_LF_DELTAS];
guint8 segmentation_abs_delta;
GstVp9SegmentationInfoData segmentation[GST_VP9_MAX_SEGMENTS];
ReferenceSize reference[GST_VP9_REF_FRAMES];
} GstVp9ParserPrivate;
static gint32
gst_vp9_read_signed_bits (GstBitReader * br, int bits)
{
const gint32 value = gst_vp9_read_bits (br, bits);
return gst_vp9_read_bit (br) ? -value : value;
}
static gboolean
verify_frame_marker (GstBitReader * br)
{
guint8 frame_marker = gst_vp9_read_bits (br, 2);
if (frame_marker != GST_VP9_FRAME_MARKER) {
GST_ERROR ("Invalid VP9 Frame Marker !");
return FALSE;
}
return TRUE;
}
static gboolean
verify_sync_code (GstBitReader * const br)
{
return (gst_vp9_read_bits (br, 24) == GST_VP9_SYNC_CODE);
}
static gboolean
parse_bitdepth_colorspace_sampling (GstBitReader * const br,
GstVp9FrameHdr * frame_hdr)
{
if (frame_hdr->profile > GST_VP9_PROFILE_1)
frame_hdr->bit_depth =
gst_vp9_read_bit (br) ? GST_VP9_BIT_DEPTH_12 : GST_VP9_BIT_DEPTH_10;
else
frame_hdr->bit_depth = GST_VP9_BIT_DEPTH_8;
frame_hdr->color_space = gst_vp9_read_bits (br, 3);
if (frame_hdr->color_space != GST_VP9_CS_SRGB) {
frame_hdr->color_range = gst_vp9_read_bit (br);
if (frame_hdr->profile == GST_VP9_PROFILE_1
|| frame_hdr->profile == GST_VP9_PROFILE_3) {
frame_hdr->subsampling_x = gst_vp9_read_bit (br);
frame_hdr->subsampling_y = gst_vp9_read_bit (br);
if (frame_hdr->subsampling_x == 1 && frame_hdr->subsampling_y == 1) {
GST_ERROR
("4:2:0 subsampling is not supported in profile_1 or profile_3");
goto error;
}
if (gst_vp9_read_bit (br)) {
GST_ERROR ("Reserved bit set!");
goto error;
}
} else {
frame_hdr->subsampling_y = frame_hdr->subsampling_x = 1;
}
} else {
frame_hdr->color_range = GST_VP9_CR_FULL;
if (frame_hdr->profile == GST_VP9_PROFILE_1
|| frame_hdr->profile == GST_VP9_PROFILE_3) {
if (gst_vp9_read_bit (br)) {
GST_ERROR ("Reserved bit set!");
goto error;
}
} else {
GST_ERROR
("4:4:4 subsampling is not supported in profile_0 and profile_2");
goto error;
}
}
return TRUE;
error:
return FALSE;
}
static guint
parse_profile (GstBitReader * br)
{
guint8 profile = gst_vp9_read_bit (br);
profile |= gst_vp9_read_bit (br) << 1;
if (profile > 2)
profile += gst_vp9_read_bit (br);
return profile;
}
static void
parse_frame_size (GstBitReader * br, guint32 * width, guint32 * height)
{
const guint32 w = gst_vp9_read_bits (br, 16) + 1;
const guint32 h = gst_vp9_read_bits (br, 16) + 1;
*width = w;
*height = h;
}
static void
parse_display_frame_size (GstBitReader * br, GstVp9FrameHdr * frame_hdr)
{
frame_hdr->display_size_enabled = gst_vp9_read_bit (br);
if (frame_hdr->display_size_enabled)
parse_frame_size (br, &frame_hdr->display_width,
&frame_hdr->display_height);
}
static void
parse_frame_size_from_refs (const GstVp9Parser * parser,
GstVp9FrameHdr * frame_hdr, GstBitReader * br)
{
gboolean found = FALSE;
int i;
GstVp9ParserPrivate *priv = GST_VP9_PARSER_GET_PRIVATE (parser);
for (i = 0; i < GST_VP9_REFS_PER_FRAME; i++) {
found = gst_vp9_read_bit (br);
if (found) {
guint8 idx = frame_hdr->ref_frame_indices[i];
frame_hdr->width = priv->reference[idx].width;
frame_hdr->height = priv->reference[idx].height;
break;
}
}
if (!found)
parse_frame_size (br, &frame_hdr->width, &frame_hdr->height);
}
static GstVp9InterpFilter
parse_interp_filter (GstBitReader * br)
{
const GstVp9InterpFilter filter_map[] = {
GST_VP9_INTERP_FILTER_EIGHTTAP_SMOOTH,
GST_VP9_INTERP_FILTER_EIGHTTAP,
GST_VP9_INTERP_FILTER_EIGHTTAP_SHARP,
GST_VP9_INTERP_FILTER_BILINEAR
};
return gst_vp9_read_bit (br) ? GST_VP9_INTERP_FILTER_SWITCHABLE :
filter_map[gst_vp9_read_bits (br, 2)];
}
static void
parse_loopfilter (GstVp9LoopFilter * lf, GstBitReader * br)
{
lf->filter_level = gst_vp9_read_bits (br, 6);
lf->sharpness_level = gst_vp9_read_bits (br, 3);
lf->mode_ref_delta_update = 0;
lf->mode_ref_delta_enabled = gst_vp9_read_bit (br);
if (lf->mode_ref_delta_enabled) {
lf->mode_ref_delta_update = gst_vp9_read_bit (br);
if (lf->mode_ref_delta_update) {
int i;
for (i = 0; i < GST_VP9_MAX_REF_LF_DELTAS; i++) {
lf->update_ref_deltas[i] = gst_vp9_read_bit (br);
if (lf->update_ref_deltas[i])
lf->ref_deltas[i] = gst_vp9_read_signed_bits (br, 6);
}
for (i = 0; i < GST_VP9_MAX_MODE_LF_DELTAS; i++) {
lf->update_mode_deltas[i] = gst_vp9_read_bit (br);
if (lf->update_mode_deltas[i])
lf->mode_deltas[i] = gst_vp9_read_signed_bits (br, 6);
}
}
}
}
static gint8
parse_delta_q (GstBitReader * br)
{
return gst_vp9_read_bit (br) ? gst_vp9_read_signed_bits (br, 4) : 0;
}
static void
parse_quantization (GstVp9QuantIndices * quant_indices, GstBitReader * br)
{
quant_indices->y_ac_qi = gst_vp9_read_bits (br, QINDEX_BITS);
quant_indices->y_dc_delta = parse_delta_q (br);
quant_indices->uv_dc_delta = parse_delta_q (br);
quant_indices->uv_ac_delta = parse_delta_q (br);
}
static void
parse_segmentation (GstVp9SegmentationInfo * seg, GstBitReader * br)
{
int i;
seg->update_map = FALSE;
seg->update_data = FALSE;
seg->enabled = gst_vp9_read_bit (br);
if (!seg->enabled)
return;
/* Segmentation map update */
seg->update_map = gst_vp9_read_bit (br);
if (seg->update_map) {
for (i = 0; i < GST_VP9_SEG_TREE_PROBS; i++) {
seg->update_tree_probs[i] = gst_vp9_read_bit (br);
seg->tree_probs[i] = seg->update_tree_probs[i] ?
gst_vp9_read_bits (br, 8) : GST_VP9_MAX_PROB;
}
seg->temporal_update = gst_vp9_read_bit (br);
if (seg->temporal_update) {
for (i = 0; i < GST_VP9_PREDICTION_PROBS; i++) {
seg->update_pred_probs[i] = gst_vp9_read_bit (br);
seg->pred_probs[i] = seg->update_pred_probs[i] ?
gst_vp9_read_bits (br, 8) : GST_VP9_MAX_PROB;
}
} else {
for (i = 0; i < GST_VP9_PREDICTION_PROBS; i++)
seg->pred_probs[i] = GST_VP9_MAX_PROB;
}
}
/* Segmentation data update */
seg->update_data = gst_vp9_read_bit (br);
if (seg->update_data) {
/* clear all features */
memset (seg->data, 0, sizeof (seg->data));
seg->abs_delta = gst_vp9_read_bit (br);
for (i = 0; i < GST_VP9_MAX_SEGMENTS; i++) {
GstVp9SegmentationInfoData *seg_data = seg->data + i;
guint8 data;
/* SEG_LVL_ALT_Q */
seg_data->alternate_quantizer_enabled = gst_vp9_read_bit (br);
if (seg_data->alternate_quantizer_enabled) {
data = gst_vp9_read_bits (br, 8);
seg_data->alternate_quantizer = gst_vp9_read_bit (br) ? -data : data;
}
/* SEG_LVL_ALT_LF */
seg_data->alternate_loop_filter_enabled = gst_vp9_read_bit (br);
if (seg_data->alternate_loop_filter_enabled) {
data = gst_vp9_read_bits (br, 6);
seg_data->alternate_loop_filter = gst_vp9_read_bit (br) ? -data : data;
}
/* SEG_LVL_REF_FRAME */
seg_data->reference_frame_enabled = gst_vp9_read_bit (br);
if (seg_data->reference_frame_enabled) {
seg_data->reference_frame = gst_vp9_read_bits (br, 2);
}
seg_data->reference_skip = gst_vp9_read_bit (br);
}
}
}
static guint32
get_max_lb_tile_cols (guint32 sb_cols)
{
gint max_log2 = 1;
while ((sb_cols >> max_log2) >= MIN_TILE_WIDTH_B64)
++max_log2;
return max_log2 - 1;
}
static guint32
get_min_lb_tile_cols (guint32 sb_cols)
{
gint min_log2 = 0;
while ((MAX_TILE_WIDTH_B64 << min_log2) < sb_cols)
++min_log2;
return min_log2;
}
static gboolean
parse_tile_info (GstVp9FrameHdr * frame_hdr, GstBitReader * br)
{
guint32 max_ones;
const guint32 sb_cols = ALIGN_SB64 (frame_hdr->width);
guint32 min_lb_tile_cols = get_min_lb_tile_cols (sb_cols);
guint32 max_lb_tile_cols = get_max_lb_tile_cols (sb_cols);
g_assert (min_lb_tile_cols <= max_lb_tile_cols);
max_ones = max_lb_tile_cols - min_lb_tile_cols;
/* columns */
frame_hdr->log2_tile_columns = min_lb_tile_cols;
while (max_ones-- && gst_vp9_read_bit (br))
frame_hdr->log2_tile_columns++;
if (frame_hdr->log2_tile_columns > 6) {
GST_ERROR ("Invalid number of tile columns..!");
return FALSE;
}
/* row */
frame_hdr->log2_tile_rows = gst_vp9_read_bit (br);
if (frame_hdr->log2_tile_rows)
frame_hdr->log2_tile_rows += gst_vp9_read_bit (br);
return TRUE;
}
static void
loop_filter_update (GstVp9Parser * parser, const GstVp9LoopFilter * lf)
{
GstVp9ParserPrivate *priv = GST_VP9_PARSER_GET_PRIVATE (parser);
int i;
for (i = 0; i < GST_VP9_MAX_REF_LF_DELTAS; i++) {
if (lf->update_ref_deltas[i])
priv->ref_deltas[i] = lf->ref_deltas[i];
}
for (i = 0; i < GST_VP9_MAX_MODE_LF_DELTAS; i++) {
if (lf->update_mode_deltas[i])
priv->mode_deltas[i] = lf->mode_deltas[i];
}
}
static guint8
seg_get_base_qindex (const GstVp9Parser * parser,
const GstVp9FrameHdr * frame_hdr, int segid)
{
int seg_base = frame_hdr->quant_indices.y_ac_qi;
GstVp9ParserPrivate *priv = GST_VP9_PARSER_GET_PRIVATE (parser);
const GstVp9SegmentationInfoData *seg = priv->segmentation + segid;
/* DEBUG("id = %d, seg_base = %d, seg enable = %d, alt eanble = %d, abs = %d, alt= %d\n",segid,
seg_base, frame_hdr->segmentation.enabled, seg->alternate_quantizer_enabled, priv->segmentation_abs_delta, seg->alternate_quantizer);
*/
if (frame_hdr->segmentation.enabled && seg->alternate_quantizer_enabled) {
if (priv->segmentation_abs_delta)
seg_base = seg->alternate_quantizer;
else
seg_base += seg->alternate_quantizer;
}
return clamp (seg_base, 0, MAXQ);
}
static guint8
seg_get_filter_level (const GstVp9Parser * parser,
const GstVp9FrameHdr * frame_hdr, int segid)
{
int seg_filter = frame_hdr->loopfilter.filter_level;
GstVp9ParserPrivate *priv = GST_VP9_PARSER_GET_PRIVATE (parser);
const GstVp9SegmentationInfoData *seg = priv->segmentation + segid;
if (frame_hdr->segmentation.enabled && seg->alternate_loop_filter_enabled) {
if (priv->segmentation_abs_delta)
seg_filter = seg->alternate_loop_filter;
else
seg_filter += seg->alternate_loop_filter;
}
return clamp (seg_filter, 0, GST_VP9_MAX_LOOP_FILTER);
}
/*save segmentation info from frame header to parser*/
static void
segmentation_save (GstVp9Parser * parser, const GstVp9FrameHdr * frame_hdr)
{
const GstVp9SegmentationInfo *info = &frame_hdr->segmentation;
if (!info->enabled)
return;
if (info->update_map) {
g_assert (G_N_ELEMENTS (parser->mb_segment_tree_probs) ==
G_N_ELEMENTS (info->tree_probs));
g_assert (G_N_ELEMENTS (parser->segment_pred_probs) ==
G_N_ELEMENTS (info->pred_probs));
memcpy (parser->mb_segment_tree_probs, info->tree_probs,
sizeof (info->tree_probs));
memcpy (parser->segment_pred_probs, info->pred_probs,
sizeof (info->pred_probs));
}
if (info->update_data) {
GstVp9ParserPrivate *priv = GST_VP9_PARSER_GET_PRIVATE (parser);
priv->segmentation_abs_delta = info->abs_delta;
g_assert (G_N_ELEMENTS (priv->segmentation) == G_N_ELEMENTS (info->data));
memcpy (priv->segmentation, info->data, sizeof (info->data));
}
}
static void
segmentation_update (GstVp9Parser * parser, const GstVp9FrameHdr * frame_hdr)
{
int i = 0;
const GstVp9ParserPrivate *priv = GST_VP9_PARSER_GET_PRIVATE (parser);
const GstVp9LoopFilter *lf = &frame_hdr->loopfilter;
const GstVp9QuantIndices *quant_indices = &frame_hdr->quant_indices;
int default_filter = lf->filter_level;
const int scale = 1 << (default_filter >> 5);
segmentation_save (parser, frame_hdr);
for (i = 0; i < GST_VP9_MAX_SEGMENTS; i++) {
guint8 q = seg_get_base_qindex (parser, frame_hdr, i);
GstVp9Segmentation *seg = parser->segmentation + i;
const GstVp9SegmentationInfoData *info = priv->segmentation + i;
seg->luma_dc_quant_scale =
vp9_dc_quant (q, quant_indices->y_dc_delta, frame_hdr->bit_depth);
seg->luma_ac_quant_scale = vp9_ac_quant (q, 0, frame_hdr->bit_depth);
seg->chroma_dc_quant_scale =
vp9_dc_quant (q, quant_indices->uv_dc_delta, frame_hdr->bit_depth);
seg->chroma_ac_quant_scale =
vp9_ac_quant (q, quant_indices->uv_ac_delta, frame_hdr->bit_depth);
if (lf->filter_level) {
guint8 filter = seg_get_filter_level (parser, frame_hdr, i);
if (!lf->mode_ref_delta_enabled) {
memset (seg->filter_level, filter, sizeof (seg->filter_level));
} else {
int ref, mode;
const int intra_filter =
filter + priv->ref_deltas[GST_VP9_REF_FRAME_INTRA] * scale;
seg->filter_level[GST_VP9_REF_FRAME_INTRA][0] =
clamp (intra_filter, 0, GST_VP9_MAX_LOOP_FILTER);
for (ref = GST_VP9_REF_FRAME_LAST; ref < GST_VP9_REF_FRAME_MAX; ++ref) {
for (mode = 0; mode < GST_VP9_MAX_MODE_LF_DELTAS; ++mode) {
const int inter_filter = filter + priv->ref_deltas[ref] * scale
+ priv->mode_deltas[mode] * scale;
seg->filter_level[ref][mode] =
clamp (inter_filter, 0, GST_VP9_MAX_LOOP_FILTER);
}
}
}
}
seg->reference_frame_enabled = info->reference_frame_enabled;;
seg->reference_frame = info->reference_frame;
seg->reference_skip = info->reference_skip;
}
}
static void
reference_update (GstVp9Parser * parser, const GstVp9FrameHdr * const frame_hdr)
{
guint8 flag = 1;
guint8 refresh_frame_flags;
int i;
GstVp9ParserPrivate *priv = GST_VP9_PARSER_GET_PRIVATE (parser);
ReferenceSize *reference = priv->reference;
if (frame_hdr->frame_type == GST_VP9_KEY_FRAME) {
refresh_frame_flags = 0xff;
} else {
refresh_frame_flags = frame_hdr->refresh_frame_flags;
}
for (i = 0; i < GST_VP9_REF_FRAMES; i++) {
if (refresh_frame_flags & flag) {
reference[i].width = frame_hdr->width;
reference[i].height = frame_hdr->height;
}
flag <<= 1;
}
}
static inline int
frame_is_intra_only (const GstVp9FrameHdr * frame_hdr)
{
return frame_hdr->frame_type == GST_VP9_KEY_FRAME || frame_hdr->intra_only;
}
static void
set_default_lf_deltas (GstVp9Parser * parser)
{
GstVp9ParserPrivate *priv = GST_VP9_PARSER_GET_PRIVATE (parser);
priv->ref_deltas[GST_VP9_REF_FRAME_INTRA] = 1;
priv->ref_deltas[GST_VP9_REF_FRAME_LAST] = 0;
priv->ref_deltas[GST_VP9_REF_FRAME_GOLDEN] = -1;
priv->ref_deltas[GST_VP9_REF_FRAME_ALTREF] = -1;
priv->mode_deltas[0] = 0;
priv->mode_deltas[1] = 0;
}
static void
set_default_segmentation_info (GstVp9Parser * parser)
{
GstVp9ParserPrivate *priv = GST_VP9_PARSER_GET_PRIVATE (parser);
memset (priv->segmentation, 0, sizeof (priv->segmentation));
priv->segmentation_abs_delta = FALSE;
}
static void
setup_past_independence (GstVp9Parser * parser,
GstVp9FrameHdr * const frame_hdr)
{
set_default_lf_deltas (parser);
set_default_segmentation_info (parser);
memset (frame_hdr->ref_frame_sign_bias, 0,
sizeof (frame_hdr->ref_frame_sign_bias));
}
static void
gst_vp9_parser_init (GstVp9Parser * parser)
{
GstVp9ParserPrivate *priv = parser->priv;
memset (parser, 0, sizeof (GstVp9Parser));
memset (priv, 0, sizeof (GstVp9ParserPrivate));
parser->priv = priv;
}
static GstVp9ParserResult
gst_vp9_parser_update (GstVp9Parser * parser, GstVp9FrameHdr * const frame_hdr)
{
if (frame_hdr->frame_type == GST_VP9_KEY_FRAME)
gst_vp9_parser_init (parser);
if (frame_is_intra_only (frame_hdr) || frame_hdr->error_resilient_mode)
setup_past_independence (parser, frame_hdr);
loop_filter_update (parser, &frame_hdr->loopfilter);
segmentation_update (parser, frame_hdr);
reference_update (parser, frame_hdr);
return GST_VP9_PARSER_OK;
}
/******** API *************/
/**
* gst_vp9_parser_new:
*
* Creates a new #GstVp9Parser. It should be freed with
* gst_vp9_parser_free after use.
*
* Returns: a new #GstVp9Parser
*/
GstVp9Parser *
gst_vp9_parser_new (void)
{
GstVp9Parser *parser;
GstVp9ParserPrivate *priv;
INITIALIZE_DEBUG_CATEGORY;
GST_DEBUG ("Create VP9 Parser");
parser = g_slice_new (GstVp9Parser);
if (!parser)
return NULL;
priv = g_slice_new (GstVp9ParserPrivate);
if (!priv)
return NULL;
parser->priv = priv;
gst_vp9_parser_init (parser);
return parser;
}
/**
* gst_vp9_parser_free:
* @parser: the #GstVp9Parser to free
*
* Frees @parser and sets it to %NULL
*/
void
gst_vp9_parser_free (GstVp9Parser * parser)
{
if (parser) {
if (parser->priv) {
g_slice_free (GstVp9ParserPrivate, parser->priv);
parser->priv = NULL;
}
g_slice_free (GstVp9Parser, parser);
parser = NULL;
}
}
/**
* gst_vp9_parser_parse_frame_header:
* @parser: The #GstVp9Parser
* @frame_hdr: The #GstVp9FrameHdr to fill
* @data: The data to parse
* @size: The size of the @data to parse
*
* Parses the VP9 bitstream contained in @data, and fills in @frame_hdr
* with the information. The @size argument represent the whole frame size.
*
* Returns: a #GstVp9ParserResult
*
*/
GstVp9ParserResult
gst_vp9_parser_parse_frame_header (GstVp9Parser * parser,
GstVp9FrameHdr * frame_hdr, const guint8 * data, gsize size)
{
GstBitReader bit_reader;
GstBitReader *br = &bit_reader;
gst_bit_reader_init (br, data, size);
memset (frame_hdr, 0, sizeof (*frame_hdr));
/* Parsing Uncompressed Data Chunk */
if (!verify_frame_marker (br))
goto error;
frame_hdr->profile = parse_profile (br);
if (frame_hdr->profile > GST_VP9_PROFILE_UNDEFINED) {
GST_ERROR ("Stream has undefined VP9 profile !");
goto error;
}
frame_hdr->show_existing_frame = gst_vp9_read_bit (br);
if (frame_hdr->show_existing_frame) {
frame_hdr->frame_to_show = gst_vp9_read_bits (br, GST_VP9_REF_FRAMES_LOG2);
return GST_VP9_PARSER_OK;
}
frame_hdr->frame_type = gst_vp9_read_bit (br);
frame_hdr->show_frame = gst_vp9_read_bit (br);
frame_hdr->error_resilient_mode = gst_vp9_read_bit (br);
if (frame_hdr->frame_type == GST_VP9_KEY_FRAME) {
if (!verify_sync_code (br)) {
GST_ERROR ("Invalid VP9 Key-frame sync code !");
goto error;
}
if (!parse_bitdepth_colorspace_sampling (br, frame_hdr)) {
GST_ERROR ("Failed to parse color_space/bit_depth info !");
goto error;
}
parse_frame_size (br, &frame_hdr->width, &frame_hdr->height);
parse_display_frame_size (br, frame_hdr);
} else {
frame_hdr->intra_only = frame_hdr->show_frame ? 0 : gst_vp9_read_bit (br);
frame_hdr->reset_frame_context = frame_hdr->error_resilient_mode ?
0 : gst_vp9_read_bits (br, 2);
if (frame_hdr->intra_only) {
if (!verify_sync_code (br)) {
GST_ERROR ("Invalid VP9 sync code in intra-only frame !");
goto error;
}
if (frame_hdr->profile > GST_VP9_PROFILE_0) {
if (!parse_bitdepth_colorspace_sampling (br, frame_hdr)) {
GST_ERROR ("Failed to parse color_space/bit_depth info !");
goto error;
}
} else {
frame_hdr->color_space = GST_VP9_CS_BT_601;
frame_hdr->color_range = GST_VP9_CR_LIMITED;
frame_hdr->subsampling_y = frame_hdr->subsampling_x = 1;
frame_hdr->bit_depth = GST_VP9_BIT_DEPTH_8;
}
frame_hdr->refresh_frame_flags =
gst_vp9_read_bits (br, GST_VP9_REF_FRAMES);
parse_frame_size (br, &frame_hdr->width, &frame_hdr->height);
parse_display_frame_size (br, frame_hdr);
} else {
int i;
frame_hdr->refresh_frame_flags =
gst_vp9_read_bits (br, GST_VP9_REF_FRAMES);
for (i = 0; i < GST_VP9_REFS_PER_FRAME; i++) {
frame_hdr->ref_frame_indices[i] =
gst_vp9_read_bits (br, GST_VP9_REF_FRAMES_LOG2);
frame_hdr->ref_frame_sign_bias[i] = gst_vp9_read_bit (br);
}
parse_frame_size_from_refs (parser, frame_hdr, br);
parse_display_frame_size (br, frame_hdr);
frame_hdr->allow_high_precision_mv = gst_vp9_read_bit (br);
frame_hdr->mcomp_filter_type = parse_interp_filter (br);
/* Assing defalut values */
frame_hdr->color_space = GST_VP9_CS_BT_601;
frame_hdr->color_range = GST_VP9_CR_LIMITED;
frame_hdr->subsampling_y = frame_hdr->subsampling_x = 1;
frame_hdr->bit_depth = GST_VP9_BIT_DEPTH_8;
}
}
frame_hdr->refresh_frame_context =
frame_hdr->error_resilient_mode ? 0 : gst_vp9_read_bit (br);
frame_hdr->frame_parallel_decoding_mode =
frame_hdr->error_resilient_mode ? 1 : gst_vp9_read_bit (br);
frame_hdr->frame_context_idx =
gst_vp9_read_bits (br, GST_FRAME_CONTEXTS_LOG2);
/* loopfilter header */
parse_loopfilter (&frame_hdr->loopfilter, br);
/* quantization header */
parse_quantization (&frame_hdr->quant_indices, br);
/* set lossless_flag */
frame_hdr->lossless_flag = frame_hdr->quant_indices.y_ac_qi == 0 &&
frame_hdr->quant_indices.y_dc_delta == 0 &&
frame_hdr->quant_indices.uv_dc_delta == 0
&& frame_hdr->quant_indices.uv_ac_delta == 0;
/* segmentation header */
parse_segmentation (&frame_hdr->segmentation, br);
/* tile header */
if (!parse_tile_info (frame_hdr, br)) {
GST_ERROR ("Failed to parse tile info...!");
goto error;
}
/* size of the rest of the header */
frame_hdr->first_partition_size = gst_vp9_read_bits (br, 16);
if (!frame_hdr->first_partition_size) {
GST_ERROR ("Failed to parse the first partition size...!");
goto error;
}
frame_hdr->frame_header_length_in_bytes =
(gst_bit_reader_get_pos (br) + 7) / 8;
return gst_vp9_parser_update (parser, frame_hdr);
error:
return GST_VP9_PARSER_ERROR;
}

View file

@ -0,0 +1,464 @@
/*
* gstvp9parser.h
*
* Copyright (C) 2013-2014 Intel Corporation
* Copyright (C) 2015 Intel Corporation
* Author: XuGuangxin<Guangxin.Xu@intel.com>
* Author: Sreerenj Balachandran<sreerenj.balachandran@intel.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef GST_VP9_PARSER_H
#define GST_VP9_PARSER_H
#ifndef GST_USE_UNSTABLE_API
#warning "The VP9 parsing library is unstable API and may change in future."
#warning "You can define GST_USE_UNSTABLE_API to avoid this warning."
#endif
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_VP9_FRAME_MARKER 0x02
#define GST_VP9_SYNC_CODE 0x498342
#define GST_VP9_MAX_LOOP_FILTER 63
#define GST_VP9_MAX_PROB 255
#define GST_VP9_REFS_PER_FRAME 3
#define GST_VP9_REF_FRAMES_LOG2 3
#define GST_VP9_REF_FRAMES (1 << GST_VP9_REF_FRAMES_LOG2)
#define GST_FRAME_CONTEXTS_LOG2 2
#define GST_VP9_MAX_LOOP_FILTER 63
#define GST_VP9_MAX_SHARPNESS 7
#define GST_VP9_MAX_REF_LF_DELTAS 4
#define GST_VP9_MAX_MODE_LF_DELTAS 2
#define GST_VP9_SEGMENT_DELTADATA 0
#define GST_VP9_SEGMENT_ABSDATA 1
#define GST_VP9_MAX_SEGMENTS 8
#define GST_VP9_SEG_TREE_PROBS (GST_VP9_MAX_SEGMENTS-1)
#define GST_VP9_PREDICTION_PROBS 3
typedef struct _GstVp9Parser GstVp9Parser;
typedef struct _GstVp9FrameHdr GstVp9FrameHdr;
typedef struct _GstVp9LoopFilter GstVp9LoopFilter;
typedef struct _GstVp9QuantIndices GstVp9QuantIndices;
typedef struct _GstVp9Segmentation GstVp9Segmentation;
typedef struct _GstVp9SegmentationInfo GstVp9SegmentationInfo;
typedef struct _GstVp9SegmentationInfoData GstVp9SegmentationInfoData;
/**
* GstVp9ParseResult:
* @GST_VP9_PARSER_OK: The parsing went well
* @GST_VP9_PARSER_BROKEN_DATA: The data to parse is broken
* @GST_VP9_PARSER_NO_PACKET_ERROR: An error accured durint the parsing
*
* Result type of any parsing function.
*/
typedef enum
{
GST_VP9_PARSER_OK,
GST_VP9_PARSER_BROKEN_DATA,
GST_VP9_PARSER_ERROR,
} GstVp9ParserResult;
/**
* GstVp9Profile: Bitstream profiles indicated by 2-3 bits in the uncompressed header
* @GST_VP9_PROFILE_0: Profile 0, 8-bit 4:2:0 only.
* @GST_VP9_PROFILE_1: Profile 1, 8-bit 4:4:4, 4:2:2, and 4:4:0.
* @GST_VP9_PROFILE_2: Profile 2, 10-bit and 12-bit color only, with 4:2:0 sampling.
* @GST_VP9_PROFILE_3: Profile 3, 10-bit and 12-bit color only, with 4:2:2/4:4:4/4:4:0 sampling.
* @GST_VP9_PROFILE_UNDEFINED: Undefined profile
*
* VP9 Profiles
*/
typedef enum {
GST_VP9_PROFILE_0,
GST_VP9_PROFILE_1,
GST_VP9_PROFILE_2,
GST_VP9_PROFILE_3,
GST_VP9_PROFILE_UNDEFINED
} GstVP9Profile;
/**
* GstVp9FrameType:
* @GST_VP9_KEY_FRAME: Key frame, only have intra blocks
* @GST_VP9_INTER_FRAME: Inter frame, both intra and inter blocks
*
* VP9 frame types
*/
typedef enum {
GST_VP9_KEY_FRAME = 0,
GST_VP9_INTER_FRAME = 1
} GstVp9FrameType;
/**
* GstVp9BitDepth:
* @GST_VP9_BIT_DEPTH_8: Bit depth is 8
* @GST_VP9_BIT_DEPTH_10 Bit depth is 10
* @GST_VP9_BIT_DEPTH_12:Bit depth is 12
*
* Bit depths of encoded frames
*/
typedef enum {
GST_VP9_BIT_DEPTH_8 = 8,
GST_VP9_BIT_DEPTH_10 = 10,
GST_VP9_BIT_DEPTH_12 = 12
} GstVp9BitDepth;
/**
* GstVp9ColorSpace:
* @GST_VP9_CS_UNKNOWN: Unknown color space
* @GST_VP9_CS_BT_601: BT.601
* @GST_VP9_CS_BT_709: BT.709
* @GST_VP9_CS_SMPTE_170: SMPTE.170
* @GST_VP9_CS_SMPTE_240: SMPTE.240
* @GST_VP9_CS_BT_2020: BT.2020
* @GST_VP9_CS_RESERVED: Reserved
* @GST_VP9_CS_SRGB: sRGB
*
* Supported ColorSpace standards
*/
typedef enum {
GST_VP9_CS_UNKNOWN = 0,
GST_VP9_CS_BT_601 = 1,
GST_VP9_CS_BT_709 = 2,
GST_VP9_CS_SMPTE_170 = 3,
GST_VP9_CS_SMPTE_240 = 4,
GST_VP9_CS_BT_2020 = 5,
GST_VP9_CS_RESERVED_2 = 6,
GST_VP9_CS_SRGB = 7
} GstVp9ColorSpace;
/**
* GstVp9ColorRange:
* @GST_VP9_CR_LIMITED: Y range is [16-235], UV range is [16-240]
* @GST_VP9_CR_FULL: Full range for Y,U and V [0-255]
*
* Possible color value ranges
*/
typedef enum {
GST_VP9_CR_LIMITED,
GST_VP9_CR_FULL
} GstVp9ColorRange;
/**
* GstVp9InterpFilter:
* @GST_VP9_INTERP_FILTER_EIGHTTAP: EightTap interpolation filter
* @GST_VP9_INTERP_FILTER_EIGHTTAP_SMOOTH: Smooth interpolation filter
* @GST_VP9_INTERP_FILTER_EIGHTTAP_SHARP: Shart interpolation filter
* @GST_VP9_INTERP_FILTER_BILINEAR: Bilinear interpolation filter
* @GST_VP9_INTERP_FILTER_SWITCHABLE: Selectable interpolation filter
*
* Interpolation Filters Types
*/
typedef enum {
GST_VP9_INTERP_FILTER_EIGHTTAP = 0,
GST_VP9_INTERP_FILTER_EIGHTTAP_SMOOTH = 1,
GST_VP9_INTERP_FILTER_EIGHTTAP_SHARP = 2,
GST_VP9_INTERP_FILTER_BILINEAR = 3,
GST_VP9_INTERP_FILTER_SWITCHABLE = 4
} GstVp9InterpFilter;
/**
* GstVp9RefFrameType:
* @GST_VP9_REF_FRAME_INTRA: Intra reference frame
* @GST_VP9_REF_FRAME_LAST: Last Reference frame
* @GST_VP9_REF_FRAME_GOLDEN: Golden Reference frame
* @GST_VP9_REF_FRAME_ALTREF: Alternate Reference frame
* @GST_VP9_REF_FRAME_MAX:
*
* Reference Frame types
*/
typedef enum {
GST_VP9_REF_FRAME_INTRA = 0,
GST_VP9_REF_FRAME_LAST = 1,
GST_VP9_REF_FRAME_GOLDEN = 2,
GST_VP9_REF_FRAME_ALTREF = 3,
GST_VP9_REF_FRAME_MAX = 4
} GstVp9RefFrameType;
/**
* GstVp9QuantIndices:
* @y_ac_qi: indicates the dequantization table index used for the
* luma AC coefficients
* @y_dc_delta: indicates the delta value that is added to the
* baseline index to obtain the luma DC coefficient dequantization
* index
* @uv_dc_delta: indicates the delta value that is added to the
* baseline index to obtain the chroma DC coefficient dequantization
* index
* @uv_ac_delta: indicates the delta value that is added to the
* baseline index to obtain the chroma AC coefficient dequantization
* index
*
* Dequantization indices.
*/
struct _GstVp9QuantIndices
{
guint8 y_ac_qi;
gint8 y_dc_delta;
gint8 uv_dc_delta;
gint8 uv_ac_delta;
};
/**
* GstVp9MbLoofFilter:
* @filter_level: indicates loop filter level for the current frame
* @sharpness_level: indicates sharpness level for thecurrent frame
* @mode_ref_delta_enabled: indicate if filter adjust is on
* @mode_ref_delta_update: indicates if the delta values used in an
* adjustment are updated in the current frame
* @update_ref_deltas: indicate which ref deltas are updated
* @ref_deltas: Loop filter strength adjustments based on
* frame type (intra, inter)
* @update_mode_deltas: indicate with mode deltas are updated
* @mode_deltas: Loop filter strength adjustments based on
* mode (zero, new mv)
*
* Loop filter values
*/
struct _GstVp9LoopFilter {
gint filter_level;
gint sharpness_level;
guint8 mode_ref_delta_enabled;
guint8 mode_ref_delta_update;
guint8 update_ref_deltas[GST_VP9_MAX_REF_LF_DELTAS];
gint8 ref_deltas[GST_VP9_MAX_REF_LF_DELTAS];
guint8 update_mode_deltas[GST_VP9_MAX_MODE_LF_DELTAS];
gint8 mode_deltas[GST_VP9_MAX_MODE_LF_DELTAS];
};
/**
* GstVp9SegmentationInfoData:
* @alternate_quantizer_enabled: indicate alternate quantizer enabled at segment level
* @alternate_quantizer: alternate quantizer value
* @alternate_loop_filter_enabled: indicate alternate loop filter enabled at segment level
* @alternate_loop_filter: alternate loop filter
* @reference_frame_enabled: indicate alternate reference frame at segment level
* @reference_frame: alternate reference frame
* @reference_skip: a block skip mode that implies both the use of a (0,0)
* motion vector and that no residual will be coded.
*
* Segemtnation info for each segment
*
*/
struct _GstVp9SegmentationInfoData {
/* SEG_LVL_ALT_Q */
guint8 alternate_quantizer_enabled;
gint16 alternate_quantizer;
/* SEG_LVL_ALT_LF */
guint8 alternate_loop_filter_enabled;
gint8 alternate_loop_filter;
/* SEG_LVL_REF_FRAME */
guint8 reference_frame_enabled;
gint reference_frame;
guint8 reference_skip;
};
/**
* GstVp9SegmentationInfo:
* @enabled: enables the segmentation feature for the current frame
* @update_map: determines if segmentation is updated in the current frame
* @update_tree_probs: determines if tree probabilities updated or not
* @tree_probs: segment tree probabilities
* @update_pred_probs:determines if prediction probabilities updated or not
* @pred_probs: prediction probabilities
* @abs_delta: interpretation of segment data values
* @temporal_update: type of map update
* @update_data: indicates if the segment feature data
* is updated in the current frame
* @data: segment feature data
*
* Segmentation info
*/
struct _GstVp9SegmentationInfo {
/* enable in setup_segmentation*/
guint8 enabled;
/* update_map in setup_segmentation*/
guint8 update_map;
/* tree_probs exist or not*/
guint8 update_tree_probs[GST_VP9_SEG_TREE_PROBS];
guint8 tree_probs[GST_VP9_SEG_TREE_PROBS];
/* pred_probs exist or not*/
guint8 update_pred_probs[GST_VP9_PREDICTION_PROBS];
guint8 pred_probs[GST_VP9_PREDICTION_PROBS];
/* abs_delta in setup_segmentation */
guint8 abs_delta;
/* temporal_update in setup_segmentation */
guint8 temporal_update;
/* update_data in setup_segmentation*/
guint8 update_data;
GstVp9SegmentationInfoData data[GST_VP9_MAX_SEGMENTS];
};
/**
* GstVp9FrameHdr:
* @profile: encoded profile
* @show_existing_frame: display already decoded frame instead of doing the decoding
* @frame_to_show: which frame to show if show_existing_frame is true
* @frame_type: frame type
* @show_frame: indicate whether is it displayable frame or not
* @error_resilient_mode: error resilent mode
* @subsampling_x: horizontal subsampling
* @subsampling_y: vertical subsampling
* @width: frame width
* @height: frame height
* @display_size_enabled: display size enabled (cropping)
* @display_width: display width
* @display_height: display height
* @frame_context_idx: frame context index
* @bit_depth: bit depth of the stream
* @color_space: color space standard
* @color_range: color range standard
* @intra_only: intra only frame
* @reset_frame_context: reset frame context
* @refresh_frame_flags: refresh reference frame flags
* @ref_frame_indices: reference frame index
* @ref_frame_sign_bias: sign bias for selecting altref,last and golden frames
* @allow_high_precision_mv: allow hight precision motion vector
* @mcomp_filter_type: interpolation filter type
* @refresh_frame_context: refresh frame context indicator
* @frame_parallel_decoding_mode: enable or disable parallel decoding support.
* @loopfilter: loopfilter values
* @quant_indices: quantization indeces
* @segmentation: segmentation info
* @log2_tile_rows: tile row indicator
* @log2_tile_columns: tile column indicator
* @first_partition_size: first partition size (after the uncompressed header)
* @lossless_flag: lossless mode decode
* @frame_header_length_in_bytes: length of uncompressed header
*
* Frame header
*/
struct _GstVp9FrameHdr
{
guint profile;
guint8 show_existing_frame;
gint frame_to_show;
guint frame_type;
guint8 show_frame;
guint8 error_resilient_mode;
gint subsampling_x;
gint subsampling_y;
guint32 width;
guint32 height;
guint8 display_size_enabled;
guint32 display_width;
guint32 display_height;
guint frame_context_idx;
guint bit_depth;
guint color_space;
guint color_range;
guint8 intra_only;
gint reset_frame_context;
gint refresh_frame_flags;
gint ref_frame_indices[GST_VP9_REFS_PER_FRAME];
gint ref_frame_sign_bias[GST_VP9_REFS_PER_FRAME];
gint allow_high_precision_mv;
guint8 mcomp_filter_type;
gint refresh_frame_context;
/* frame_parallel_decoding_mode in vp9 code*/
gint frame_parallel_decoding_mode;
GstVp9LoopFilter loopfilter;
GstVp9QuantIndices quant_indices;
GstVp9SegmentationInfo segmentation;
gint log2_tile_rows;
gint log2_tile_columns;
guint32 first_partition_size;
/* calculated values */
guint lossless_flag;
guint32 frame_header_length_in_bytes;
};
/**
* GstVp9Segmentation:
* @filter_level: loop filter level
* @luma_ac_quant_scale: AC quant scale for luma(Y) component
* @luma_dc_quant_scale: DC quant scale for luma(Y) component
* @chroma_ac_quant_scale AC quant scale for chroma(U/V) component
* @chroma_dc_quant_scale: DC quant scale for chroma (U/V) component
* @reference_frame_enabled: alternate reference frame enablement
* @reference_frame: alternate reference frame
* @reference_skip: a block skip mode that implies both the use of a (0,0)
* motion vector and that no residual will be coded
*
* Segmentation info kept across multipe frames
*/
struct _GstVp9Segmentation
{
guint8 filter_level[4][2];
gint16 luma_ac_quant_scale;
gint16 luma_dc_quant_scale;
gint16 chroma_ac_quant_scale;
gint16 chroma_dc_quant_scale;
guint8 reference_frame_enabled;
gint reference_frame;
guint8 reference_skip;
};
/**
* GstVp9Parser:
* @priv: GstVp9ParserPrivate struct to keep track of state variables
* @mb_segment_tree_probs: decoding tree probabilities
* @segment_pred_probs: segement prediction probabiilties
* @segmentation: Segemenation info
*
* Parser context that needs to be live across frames
*/
struct _GstVp9Parser
{
/* private stuct for tracking state variables across frames */
void *priv;
guint8 mb_segment_tree_probs[GST_VP9_SEG_TREE_PROBS];
guint8 segment_pred_probs[GST_VP9_PREDICTION_PROBS];
GstVp9Segmentation segmentation[GST_VP9_MAX_SEGMENTS];
};
GstVp9Parser * gst_vp9_parser_new (void);
GstVp9ParserResult gst_vp9_parser_parse_frame_header (GstVp9Parser* parser, GstVp9FrameHdr * frame_hdr, const guint8 * data, gsize size);
void gst_vp9_parser_free (GstVp9Parser * parser);
G_END_DECLS
#endif /* GST_VP9_PARSER_H */

View file

@ -0,0 +1,100 @@
# This file is automatically generated from the git commit history
# by tools/gen_authors.sh.
Aaron Watry <awatry@gmail.com>
Abo Talib Mahfoodh <ab.mahfoodh@gmail.com>
Adrian Grange <agrange@google.com>
Ahmad Sharif <asharif@google.com>
Alexander Voronov <avoronov@graphics.cs.msu.ru>
Alex Converse <alex.converse@gmail.com>
Alexis Ballier <aballier@gentoo.org>
Alok Ahuja <waveletcoeff@gmail.com>
Alpha Lam <hclam@google.com>
A.Mahfoodh <ab.mahfoodh@gmail.com>
Ami Fischman <fischman@chromium.org>
Andoni Morales Alastruey <ylatuya@gmail.com>
Andres Mejia <mcitadel@gmail.com>
Aron Rosenberg <arosenberg@logitech.com>
Attila Nagy <attilanagy@google.com>
changjun.yang <changjun.yang@intel.com>
chm <chm@rock-chips.com>
Christian Duvivier <cduvivier@google.com>
Daniel Kang <ddkang@google.com>
Deb Mukherjee <debargha@google.com>
Dmitry Kovalev <dkovalev@google.com>
Dragan Mrdjan <dmrdjan@mips.com>
Erik Niemeyer <erik.a.niemeyer@gmail.com>
Fabio Pedretti <fabio.ped@libero.it>
Frank Galligan <fgalligan@google.com>
Fredrik Söderquist <fs@opera.com>
Fritz Koenig <frkoenig@google.com>
Gaute Strokkenes <gaute.strokkenes@broadcom.com>
Giuseppe Scrivano <gscrivano@gnu.org>
Guillaume Martres <gmartres@google.com>
Guillermo Ballester Valor <gbvalor@gmail.com>
Hangyu Kuang <hkuang@google.com>
Henrik Lundin <hlundin@google.com>
Hui Su <huisu@google.com>
Ivan Maltz <ivanmaltz@google.com>
James Berry <jamesberry@google.com>
James Zern <jzern@google.com>
Jan Kratochvil <jan.kratochvil@redhat.com>
Janne Salonen <jsalonen@google.com>
Jeff Faust <jfaust@google.com>
Jeff Muizelaar <jmuizelaar@mozilla.com>
Jeff Petkau <jpet@chromium.org>
Jim Bankoski <jimbankoski@google.com>
Jingning Han <jingning@google.com>
Johann Koenig <johannkoenig@google.com>
John Koleszar <jkoleszar@google.com>
Joshua Bleecher Snyder <josh@treelinelabs.com>
Joshua Litt <joshualitt@google.com>
Justin Clift <justin@salasaga.org>
Justin Lebar <justin.lebar@gmail.com>
KO Myung-Hun <komh@chollian.net>
Lou Quillio <louquillio@google.com>
Luca Barbato <lu_zero@gentoo.org>
Makoto Kato <makoto.kt@gmail.com>
Mans Rullgard <mans@mansr.com>
Marco Paniconi <marpan@google.com>
Mark Mentovai <mark@chromium.org>
Martin Ettl <ettl.martin78@googlemail.com>
Martin Storsjo <martin@martin.st>
Matthew Heaney <matthewjheaney@chromium.org>
Michael Kohler <michaelkohler@live.com>
Mike Frysinger <vapier@chromium.org>
Mike Hommey <mhommey@mozilla.com>
Mikhal Shemer <mikhal@google.com>
Morton Jonuschat <yabawock@gmail.com>
Parag Salasakar <img.mips1@gmail.com>
Pascal Massimino <pascal.massimino@gmail.com>
Patrik Westin <patrik.westin@gmail.com>
Paul Wilkins <paulwilkins@google.com>
Pavol Rusnak <stick@gk2.sk>
Paweł Hajdan <phajdan@google.com>
Philip Jägenstedt <philipj@opera.com>
Priit Laes <plaes@plaes.org>
Rafael Ávila de Espíndola <rafael.espindola@gmail.com>
Rafaël Carré <funman@videolan.org>
Ralph Giles <giles@xiph.org>
Rob Bradford <rob@linux.intel.com>
Ronald S. Bultje <rbultje@google.com>
Sami Pietilä <samipietila@google.com>
Scott Graham <scottmg@chromium.org>
Scott LaVarnway <slavarnway@google.com>
Shimon Doodkin <helpmepro1@gmail.com>
Stefan Holmer <holmer@google.com>
Suman Sunkara <sunkaras@google.com>
Taekhyun Kim <takim@nvidia.com>
Takanori MATSUURA <t.matsuu@gmail.com>
Tamar Levy <tamar.levy@intel.com>
Tero Rintaluoma <teror@google.com>
Thijs Vermeir <thijsvermeir@gmail.com>
Timothy B. Terriberry <tterribe@xiph.org>
Tom Finegan <tomfinegan@google.com>
Vignesh Venkatasubramanian <vigneshv@google.com>
Yaowu Xu <yaowu@google.com>
Yunqing Wang <yunqingwang@google.com>
Google Inc.
The Mozilla Foundation
The Xiph.Org Foundation

View file

@ -0,0 +1,30 @@
Copyright (c) 2010, The WebM Project authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Google, nor the WebM Project, nor the names
of its contributors may be used to endorse or promote products
derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,22 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the WebM Project.
Google hereby grants to you a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer, and otherwise run, modify and propagate the contents of this
implementation of VP8, where such license applies only to those patent
claims, both currently owned by Google and acquired in the future,
licensable by Google that are necessarily infringed by this
implementation of VP8. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of VP8 or any code incorporated within this
implementation of VP8 constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of VP8
shall terminate as of the date such litigation is filed.

View file

@ -0,0 +1,263 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "vp9utils.h"
static const int16_t dc_qlookup[QINDEX_RANGE] = {
4, 8, 8, 9, 10, 11, 12, 12,
13, 14, 15, 16, 17, 18, 19, 19,
20, 21, 22, 23, 24, 25, 26, 26,
27, 28, 29, 30, 31, 32, 32, 33,
34, 35, 36, 37, 38, 38, 39, 40,
41, 42, 43, 43, 44, 45, 46, 47,
48, 48, 49, 50, 51, 52, 53, 53,
54, 55, 56, 57, 57, 58, 59, 60,
61, 62, 62, 63, 64, 65, 66, 66,
67, 68, 69, 70, 70, 71, 72, 73,
74, 74, 75, 76, 77, 78, 78, 79,
80, 81, 81, 82, 83, 84, 85, 85,
87, 88, 90, 92, 93, 95, 96, 98,
99, 101, 102, 104, 105, 107, 108, 110,
111, 113, 114, 116, 117, 118, 120, 121,
123, 125, 127, 129, 131, 134, 136, 138,
140, 142, 144, 146, 148, 150, 152, 154,
156, 158, 161, 164, 166, 169, 172, 174,
177, 180, 182, 185, 187, 190, 192, 195,
199, 202, 205, 208, 211, 214, 217, 220,
223, 226, 230, 233, 237, 240, 243, 247,
250, 253, 257, 261, 265, 269, 272, 276,
280, 284, 288, 292, 296, 300, 304, 309,
313, 317, 322, 326, 330, 335, 340, 344,
349, 354, 359, 364, 369, 374, 379, 384,
389, 395, 400, 406, 411, 417, 423, 429,
435, 441, 447, 454, 461, 467, 475, 482,
489, 497, 505, 513, 522, 530, 539, 549,
559, 569, 579, 590, 602, 614, 626, 640,
654, 668, 684, 700, 717, 736, 755, 775,
796, 819, 843, 869, 896, 925, 955, 988,
1022, 1058, 1098, 1139, 1184, 1232, 1282, 1336,
};
static const int16_t dc_qlookup_10[QINDEX_RANGE] = {
4, 9, 10, 13, 15, 17, 20, 22,
25, 28, 31, 34, 37, 40, 43, 47,
50, 53, 57, 60, 64, 68, 71, 75,
78, 82, 86, 90, 93, 97, 101, 105,
109, 113, 116, 120, 124, 128, 132, 136,
140, 143, 147, 151, 155, 159, 163, 166,
170, 174, 178, 182, 185, 189, 193, 197,
200, 204, 208, 212, 215, 219, 223, 226,
230, 233, 237, 241, 244, 248, 251, 255,
259, 262, 266, 269, 273, 276, 280, 283,
287, 290, 293, 297, 300, 304, 307, 310,
314, 317, 321, 324, 327, 331, 334, 337,
343, 350, 356, 362, 369, 375, 381, 387,
394, 400, 406, 412, 418, 424, 430, 436,
442, 448, 454, 460, 466, 472, 478, 484,
490, 499, 507, 516, 525, 533, 542, 550,
559, 567, 576, 584, 592, 601, 609, 617,
625, 634, 644, 655, 666, 676, 687, 698,
708, 718, 729, 739, 749, 759, 770, 782,
795, 807, 819, 831, 844, 856, 868, 880,
891, 906, 920, 933, 947, 961, 975, 988,
1001, 1015, 1030, 1045, 1061, 1076, 1090, 1105,
1120, 1137, 1153, 1170, 1186, 1202, 1218, 1236,
1253, 1271, 1288, 1306, 1323, 1342, 1361, 1379,
1398, 1416, 1436, 1456, 1476, 1496, 1516, 1537,
1559, 1580, 1601, 1624, 1647, 1670, 1692, 1717,
1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929,
1958, 1990, 2021, 2054, 2088, 2123, 2159, 2197,
2236, 2276, 2319, 2363, 2410, 2458, 2508, 2561,
2616, 2675, 2737, 2802, 2871, 2944, 3020, 3102,
3188, 3280, 3375, 3478, 3586, 3702, 3823, 3953,
4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347,
};
static const int16_t dc_qlookup_12[QINDEX_RANGE] = {
4, 12, 18, 25, 33, 41, 50, 60,
70, 80, 91, 103, 115, 127, 140, 153,
166, 180, 194, 208, 222, 237, 251, 266,
281, 296, 312, 327, 343, 358, 374, 390,
405, 421, 437, 453, 469, 484, 500, 516,
532, 548, 564, 580, 596, 611, 627, 643,
659, 674, 690, 706, 721, 737, 752, 768,
783, 798, 814, 829, 844, 859, 874, 889,
904, 919, 934, 949, 964, 978, 993, 1008,
1022, 1037, 1051, 1065, 1080, 1094, 1108, 1122,
1136, 1151, 1165, 1179, 1192, 1206, 1220, 1234,
1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342,
1368, 1393, 1419, 1444, 1469, 1494, 1519, 1544,
1569, 1594, 1618, 1643, 1668, 1692, 1717, 1741,
1765, 1789, 1814, 1838, 1862, 1885, 1909, 1933,
1957, 1992, 2027, 2061, 2096, 2130, 2165, 2199,
2233, 2267, 2300, 2334, 2367, 2400, 2434, 2467,
2499, 2532, 2575, 2618, 2661, 2704, 2746, 2788,
2830, 2872, 2913, 2954, 2995, 3036, 3076, 3127,
3177, 3226, 3275, 3324, 3373, 3421, 3469, 3517,
3565, 3621, 3677, 3733, 3788, 3843, 3897, 3951,
4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420,
4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942,
5013, 5083, 5153, 5222, 5291, 5367, 5442, 5517,
5591, 5665, 5745, 5825, 5905, 5984, 6063, 6149,
6234, 6319, 6404, 6495, 6587, 6678, 6769, 6867,
6966, 7064, 7163, 7269, 7376, 7483, 7599, 7715,
7832, 7958, 8085, 8214, 8352, 8492, 8635, 8788,
8945, 9104, 9275, 9450, 9639, 9832, 10031, 10245,
10465, 10702, 10946, 11210, 11482, 11776, 12081, 12409,
12750, 13118, 13501, 13913, 14343, 14807, 15290, 15812,
16356, 16943, 17575, 18237, 18949, 19718, 20521, 21387,
};
static const int16_t ac_qlookup[QINDEX_RANGE] = {
4, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46,
47, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 66, 67, 68, 69, 70,
71, 72, 73, 74, 75, 76, 77, 78,
79, 80, 81, 82, 83, 84, 85, 86,
87, 88, 89, 90, 91, 92, 93, 94,
95, 96, 97, 98, 99, 100, 101, 102,
104, 106, 108, 110, 112, 114, 116, 118,
120, 122, 124, 126, 128, 130, 132, 134,
136, 138, 140, 142, 144, 146, 148, 150,
152, 155, 158, 161, 164, 167, 170, 173,
176, 179, 182, 185, 188, 191, 194, 197,
200, 203, 207, 211, 215, 219, 223, 227,
231, 235, 239, 243, 247, 251, 255, 260,
265, 270, 275, 280, 285, 290, 295, 300,
305, 311, 317, 323, 329, 335, 341, 347,
353, 359, 366, 373, 380, 387, 394, 401,
408, 416, 424, 432, 440, 448, 456, 465,
474, 483, 492, 501, 510, 520, 530, 540,
550, 560, 571, 582, 593, 604, 615, 627,
639, 651, 663, 676, 689, 702, 715, 729,
743, 757, 771, 786, 801, 816, 832, 848,
864, 881, 898, 915, 933, 951, 969, 988,
1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151,
1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343,
1369, 1396, 1423, 1451, 1479, 1508, 1537, 1567,
1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
};
static const int16_t ac_qlookup_10[QINDEX_RANGE] = {
4, 9, 11, 13, 16, 18, 21, 24,
27, 30, 33, 37, 40, 44, 48, 51,
55, 59, 63, 67, 71, 75, 79, 83,
88, 92, 96, 100, 105, 109, 114, 118,
122, 127, 131, 136, 140, 145, 149, 154,
158, 163, 168, 172, 177, 181, 186, 190,
195, 199, 204, 208, 213, 217, 222, 226,
231, 235, 240, 244, 249, 253, 258, 262,
267, 271, 275, 280, 284, 289, 293, 297,
302, 306, 311, 315, 319, 324, 328, 332,
337, 341, 345, 349, 354, 358, 362, 367,
371, 375, 379, 384, 388, 392, 396, 401,
409, 417, 425, 433, 441, 449, 458, 466,
474, 482, 490, 498, 506, 514, 523, 531,
539, 547, 555, 563, 571, 579, 588, 596,
604, 616, 628, 640, 652, 664, 676, 688,
700, 713, 725, 737, 749, 761, 773, 785,
797, 809, 825, 841, 857, 873, 889, 905,
922, 938, 954, 970, 986, 1002, 1018, 1038,
1058, 1078, 1098, 1118, 1138, 1158, 1178, 1198,
1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386,
1411, 1435, 1463, 1491, 1519, 1547, 1575, 1603,
1631, 1663, 1695, 1727, 1759, 1791, 1823, 1859,
1895, 1931, 1967, 2003, 2039, 2079, 2119, 2159,
2199, 2239, 2283, 2327, 2371, 2415, 2459, 2507,
2555, 2603, 2651, 2703, 2755, 2807, 2859, 2915,
2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391,
3455, 3523, 3591, 3659, 3731, 3803, 3876, 3952,
4028, 4104, 4184, 4264, 4348, 4432, 4516, 4604,
4692, 4784, 4876, 4972, 5068, 5168, 5268, 5372,
5476, 5584, 5692, 5804, 5916, 6032, 6148, 6268,
6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312,
};
static const int16_t ac_qlookup_12[QINDEX_RANGE] = {
4, 13, 19, 27, 35, 44, 54, 64,
75, 87, 99, 112, 126, 139, 154, 168,
183, 199, 214, 230, 247, 263, 280, 297,
314, 331, 349, 366, 384, 402, 420, 438,
456, 475, 493, 511, 530, 548, 567, 586,
604, 623, 642, 660, 679, 698, 716, 735,
753, 772, 791, 809, 828, 846, 865, 884,
902, 920, 939, 957, 976, 994, 1012, 1030,
1049, 1067, 1085, 1103, 1121, 1139, 1157, 1175,
1193, 1211, 1229, 1246, 1264, 1282, 1299, 1317,
1335, 1352, 1370, 1387, 1405, 1422, 1440, 1457,
1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595,
1627, 1660, 1693, 1725, 1758, 1791, 1824, 1856,
1889, 1922, 1954, 1987, 2020, 2052, 2085, 2118,
2150, 2183, 2216, 2248, 2281, 2313, 2346, 2378,
2411, 2459, 2508, 2556, 2605, 2653, 2701, 2750,
2798, 2847, 2895, 2943, 2992, 3040, 3088, 3137,
3185, 3234, 3298, 3362, 3426, 3491, 3555, 3619,
3684, 3748, 3812, 3876, 3941, 4005, 4069, 4149,
4230, 4310, 4390, 4470, 4550, 4631, 4711, 4791,
4871, 4967, 5064, 5160, 5256, 5352, 5448, 5544,
5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410,
6522, 6650, 6778, 6906, 7034, 7162, 7290, 7435,
7579, 7723, 7867, 8011, 8155, 8315, 8475, 8635,
8795, 8956, 9132, 9308, 9484, 9660, 9836, 10028,
10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661,
11885, 12109, 12333, 12573, 12813, 13053, 13309, 13565,
13821, 14093, 14365, 14637, 14925, 15213, 15502, 15806,
16110, 16414, 16734, 17054, 17390, 17726, 18062, 18414,
18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486,
21902, 22334, 22766, 23214, 23662, 24126, 24590, 25070,
25551, 26047, 26559, 27071, 27599, 28143, 28687, 29247,
};
int clamp(int value, int low, int high)
{
return value < low ? low : (value > high ? high : value);
}
int16_t vp9_dc_quant(int qindex, int delta, int bit_depth)
{
const uint8_t q_table_idx = clamp(qindex + delta, 0, MAXQ);
switch (bit_depth) {
case 8:
return dc_qlookup[q_table_idx];
case 10:
return dc_qlookup_10[q_table_idx];
case 12:
return dc_qlookup_12[q_table_idx];
default:
return -1;
}
return -1;
}
int16_t vp9_ac_quant(int qindex, int delta, int bit_depth)
{
const uint8_t q_table_idx = clamp(qindex + delta, 0, MAXQ);
switch (bit_depth) {
case 8:
return ac_qlookup[q_table_idx];
case 10:
return ac_qlookup_10[q_table_idx];
case 12:
return ac_qlookup_12[q_table_idx];
default:
return -1;
}
return -1;
}

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef __VP9_QUANT_H__
#define __VP9_QUANT_H__
#include <stdint.h>
#define MAXQ 255
#define QINDEX_RANGE 256
#define QINDEX_BITS 8
int clamp(int value, int low, int high);
int16_t vp9_dc_quant(int qindex, int delta, int bit_depth);
int16_t vp9_ac_quant(int qindex, int delta, int bit_depth);
#endif //__VP9_QUANT_H__