mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
tests: add standalone program for VP8 parser.
Add standalone test application that demonstrates how to use the new VP8 bitstream parsing library, while also allowing simple debugging/ tracing of IVF files. [clean-ups, updated to new parser API] Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
This commit is contained in:
parent
26baaf51a1
commit
bf6959000f
2 changed files with 401 additions and 1 deletions
|
@ -11,6 +11,11 @@ else
|
|||
GST_SOUNDTOUCH_TESTS =
|
||||
endif
|
||||
|
||||
GST_VP8PARSER_TESTS = vp8parser-test
|
||||
vp8parser_test_SOURCES = vp8parser-test.c
|
||||
vp8parser_test_CFLAGS = -I$(top_srcdir)/gst-libs $(GST_CFLAGS)
|
||||
vp8parser_test_LDADD = $(top_builddir)/gst-libs/gst/codecparsers/libgstcodecparsers-@GST_API_VERSION@.la $(GST_LIBS)
|
||||
|
||||
# needs porting
|
||||
#if HAVE_GTK
|
||||
#
|
||||
|
@ -25,5 +30,5 @@ endif
|
|||
GST_METADATA_TESTS =
|
||||
#endif
|
||||
|
||||
noinst_PROGRAMS = $(GST_SOUNDTOUCH_TESTS) $(GST_METADATA_TESTS)
|
||||
noinst_PROGRAMS = $(GST_SOUNDTOUCH_TESTS) $(GST_METADATA_TESTS) $(GST_VP8PARSER_TESTS)
|
||||
|
||||
|
|
395
tests/icles/vp8parser-test.c
Normal file
395
tests/icles/vp8parser-test.c
Normal file
|
@ -0,0 +1,395 @@
|
|||
/*
|
||||
* vp8parser-test.c - Print IVF/VP8 headers
|
||||
*
|
||||
* Copyright (C) 2013-2014 Intel Corporation
|
||||
* Author: Halley Zhao <halley.zhao@intel.com>
|
||||
* Author: Gwenole Beauchesne <gwenole.beauchesne@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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstbytereader.h>
|
||||
#include <gst/codecparsers/gstvp8parser.h>
|
||||
|
||||
#define FOURCC_VP80 GST_MAKE_FOURCC('V','P','8','0')
|
||||
#define IVF_FILE_HDR_SIZE 32
|
||||
#define IVF_FRAME_HDR_SIZE 12
|
||||
|
||||
/* Maximum VP8 Frame Header size in bits */
|
||||
#define VP8_FRAME_HDR_SIZE 10127
|
||||
|
||||
typedef struct _IVFFileHdr IVFFileHdr;
|
||||
struct _IVFFileHdr
|
||||
{
|
||||
guint16 version;
|
||||
guint16 length;
|
||||
guint32 fourcc;
|
||||
guint16 width;
|
||||
guint16 height;
|
||||
guint32 framerate;
|
||||
guint32 time_scale;
|
||||
guint32 num_frames;
|
||||
};
|
||||
|
||||
typedef struct _IVFFrameHdr IVFFrameHdr;
|
||||
struct _IVFFrameHdr
|
||||
{
|
||||
guint32 frame_size;
|
||||
guint64 timestamp;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
parse_ivf_file_header (IVFFileHdr * ivf_hdr, guint8 * data, guint size)
|
||||
{
|
||||
GstByteReader br;
|
||||
|
||||
if (size < IVF_FILE_HDR_SIZE) {
|
||||
g_warning ("size is smaller than IVF file header");
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_assert (data[0] == 'D' && data[1] == 'K' && data[2] == 'I'
|
||||
&& data[3] == 'F');
|
||||
|
||||
gst_byte_reader_init (&br, data, size);
|
||||
gst_byte_reader_skip (&br, 4);
|
||||
|
||||
if (!gst_byte_reader_get_uint16_le (&br, &ivf_hdr->version))
|
||||
goto error;
|
||||
g_assert (ivf_hdr->version == 0);
|
||||
|
||||
if (!gst_byte_reader_get_uint16_le (&br, &ivf_hdr->length))
|
||||
goto error;
|
||||
g_assert (ivf_hdr->length == 0x20);
|
||||
|
||||
if (!gst_byte_reader_get_uint32_le (&br, &ivf_hdr->fourcc))
|
||||
goto error;
|
||||
g_assert (ivf_hdr->fourcc == FOURCC_VP80);
|
||||
|
||||
if (!gst_byte_reader_get_uint16_le (&br, &ivf_hdr->width))
|
||||
goto error;
|
||||
if (!gst_byte_reader_get_uint16_le (&br, &ivf_hdr->height))
|
||||
goto error;
|
||||
if (!gst_byte_reader_get_uint32_le (&br, &ivf_hdr->framerate))
|
||||
goto error;
|
||||
if (!gst_byte_reader_get_uint32_le (&br, &ivf_hdr->time_scale))
|
||||
goto error;
|
||||
if (!gst_byte_reader_get_uint32_le (&br, &ivf_hdr->num_frames))
|
||||
goto error;
|
||||
|
||||
g_print ("IVF File Information:\n");
|
||||
g_print (" %-32s : %u\n", "version", ivf_hdr->version);
|
||||
g_print (" %-32s : %u\n", "length", ivf_hdr->length);
|
||||
g_print (" %-32s : '%" GST_FOURCC_FORMAT "'\n", "fourcc",
|
||||
GST_FOURCC_ARGS (ivf_hdr->fourcc));
|
||||
g_print (" %-32s : %u\n", "width", ivf_hdr->width);
|
||||
g_print (" %-32s : %u\n", "height", ivf_hdr->height);
|
||||
g_print (" %-32s : %u\n", "framerate", ivf_hdr->framerate);
|
||||
g_print (" %-32s : %u\n", "time_scale", ivf_hdr->time_scale);
|
||||
g_print (" %-32s : %u\n", "num_frames", ivf_hdr->num_frames);
|
||||
g_print ("\n");
|
||||
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_ivf_frame_header (IVFFrameHdr * frm_hdr, guint8 * data, guint size)
|
||||
{
|
||||
GstByteReader br;
|
||||
|
||||
if (size < IVF_FRAME_HDR_SIZE) {
|
||||
g_warning ("size is smaller than IVF frame header");
|
||||
goto error;
|
||||
}
|
||||
|
||||
gst_byte_reader_init (&br, data, size);
|
||||
if (!gst_byte_reader_get_uint32_le (&br, &frm_hdr->frame_size))
|
||||
goto error;
|
||||
if (!gst_byte_reader_get_uint64_le (&br, &frm_hdr->timestamp))
|
||||
goto error;
|
||||
|
||||
g_print ("IVF Frame Information:\n");
|
||||
g_print (" %-32s : %u\n", "size", frm_hdr->frame_size);
|
||||
g_print (" %-32s : %" G_GINT64_FORMAT " \n", "timestamp",
|
||||
frm_hdr->timestamp);
|
||||
g_print ("\n");
|
||||
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
print_segmentation (GstVp8Segmentation * seg)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_print ("+ Segmentation:\n");
|
||||
g_print (" %-32s : %d\n", "segmentation_enabled", seg->segmentation_enabled);
|
||||
g_print (" %-32s : %d\n", "update_mb_segmentation_map",
|
||||
seg->update_mb_segmentation_map);
|
||||
g_print (" %-32s : %d\n", "update_segment_feature_data",
|
||||
seg->update_segment_feature_data);
|
||||
|
||||
if (seg->update_segment_feature_data) {
|
||||
g_print (" %-32s : %d\n", "segment_feature_mode",
|
||||
seg->segment_feature_mode);
|
||||
g_print (" %-32s : %d", "quantizer_update_value",
|
||||
seg->quantizer_update_value[0]);
|
||||
for (i = 1; i < 4; i++) {
|
||||
g_print (", %d", seg->quantizer_update_value[i]);
|
||||
}
|
||||
g_print ("\n");
|
||||
g_print (" %-32s : %d", "lf_update_value", seg->lf_update_value[0]);
|
||||
for (i = 1; i < 4; i++) {
|
||||
g_print (", %d", seg->lf_update_value[i]);
|
||||
}
|
||||
g_print ("\n");
|
||||
}
|
||||
|
||||
if (seg->update_mb_segmentation_map) {
|
||||
g_print (" %-32s : %d", "segment_prob", seg->segment_prob[0]);
|
||||
for (i = 1; i < 3; i++) {
|
||||
g_print (", %d", seg->segment_prob[i]);
|
||||
}
|
||||
g_print ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_mb_lf_adjustments (GstVp8MbLfAdjustments * adj)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_print ("+ MB Loop-Filter Adjustments:\n");
|
||||
g_print (" %-32s : %d\n", "loop_filter_adj_enable",
|
||||
adj->loop_filter_adj_enable);
|
||||
if (adj->loop_filter_adj_enable) {
|
||||
g_print (" %-32s : %d\n", "mode_ref_lf_delta_update",
|
||||
adj->mode_ref_lf_delta_update);
|
||||
if (adj->mode_ref_lf_delta_update) {
|
||||
g_print (" %-32s : %d", "ref_frame_delta", adj->ref_frame_delta[0]);
|
||||
for (i = 1; i < 4; i++) {
|
||||
g_print (", %d", adj->ref_frame_delta[i]);
|
||||
}
|
||||
g_print ("\n");
|
||||
g_print (" %-32s : %d", "mb_mode_delta", adj->mb_mode_delta[0]);
|
||||
for (i = 1; i < 4; i++) {
|
||||
g_print (", %d", adj->mb_mode_delta[i]);
|
||||
}
|
||||
g_print ("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_quant_indices (GstVp8QuantIndices * qip)
|
||||
{
|
||||
g_print ("+ Dequantization Indices:\n");
|
||||
g_print (" %-32s : %d\n", "y_ac_qi", qip->y_ac_qi);
|
||||
g_print (" %-32s : %d\n", "y_dc_delta", qip->y_dc_delta);
|
||||
g_print (" %-32s : %d\n", "y2_dc_delta", qip->y2_dc_delta);
|
||||
g_print (" %-32s : %d\n", "y2_ac_delta", qip->y2_ac_delta);
|
||||
g_print (" %-32s : %d\n", "uv_dc_delta", qip->uv_dc_delta);
|
||||
g_print (" %-32s : %d\n", "uv_ac_delta", qip->uv_ac_delta);
|
||||
}
|
||||
|
||||
static void
|
||||
print_mv_probs (GstVp8MvProbs * probs)
|
||||
{
|
||||
gint i, j;
|
||||
|
||||
g_print ("+ MV Probabilities:\n");
|
||||
for (j = 0; j < 2; j++) {
|
||||
g_print (" %-32s : %d", j == 0 ? "row" : "column", probs->prob[j][0]);
|
||||
for (i = 1; i < 19; i++) {
|
||||
g_print (", %d", probs->prob[j][i]);
|
||||
}
|
||||
g_print ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_mode_probs (GstVp8ModeProbs * probs)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_print ("+ Intra-mode Probabilities:\n");
|
||||
g_print (" %-32s : %d", "luma", probs->y_prob[0]);
|
||||
for (i = 1; i < 4; i++) {
|
||||
g_print (", %d", probs->y_prob[i]);
|
||||
}
|
||||
g_print ("\n");
|
||||
g_print (" %-32s : %d", "chroma", probs->uv_prob[0]);
|
||||
for (i = 1; i < 3; i++) {
|
||||
g_print (", %d", probs->uv_prob[i]);
|
||||
}
|
||||
g_print ("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
print_frame_header (GstVp8FrameHdr * frame_hdr)
|
||||
{
|
||||
g_print (" %-32s : %d\n", "key_frame", frame_hdr->key_frame);
|
||||
g_print (" %-32s : %d\n", "version", frame_hdr->version);
|
||||
g_print (" %-32s : %d\n", "show_frame", frame_hdr->show_frame);
|
||||
g_print (" %-32s : %d\n", "first_part_size", frame_hdr->first_part_size);
|
||||
if (frame_hdr->key_frame) {
|
||||
g_print (" %-32s : %d\n", "width", frame_hdr->width);
|
||||
g_print (" %-32s : %d\n", "height", frame_hdr->height);
|
||||
g_print (" %-32s : %d\n", "horizontal_scale", frame_hdr->horiz_scale_code);
|
||||
g_print (" %-32s : %d\n", "vertical_scale", frame_hdr->vert_scale_code);
|
||||
}
|
||||
|
||||
if (frame_hdr->key_frame) {
|
||||
g_print (" %-32s : %d\n", "color_space", frame_hdr->color_space);
|
||||
g_print (" %-32s : %d\n", "clamping_type", frame_hdr->clamping_type);
|
||||
}
|
||||
|
||||
g_print (" %-32s : %d\n", "filter_type", frame_hdr->filter_type);
|
||||
g_print (" %-32s : %d\n", "loop_filter_level", frame_hdr->loop_filter_level);
|
||||
g_print (" %-32s : %d\n", "sharpness_level", frame_hdr->sharpness_level);
|
||||
|
||||
g_print (" %-32s : %d\n", "log2_nbr_of_dct_partitions",
|
||||
frame_hdr->log2_nbr_of_dct_partitions);
|
||||
|
||||
if (frame_hdr->key_frame) {
|
||||
g_print (" %-32s : %d\n", "refresh_entropy_probs",
|
||||
frame_hdr->refresh_entropy_probs);
|
||||
} else {
|
||||
g_print (" %-32s : %d\n", "refresh_golden_frame",
|
||||
frame_hdr->refresh_golden_frame);
|
||||
g_print (" %-32s : %d\n", "refresh_alternate_frame",
|
||||
frame_hdr->refresh_alternate_frame);
|
||||
if (!frame_hdr->refresh_golden_frame) {
|
||||
g_print (" %-32s : %d\n", "copy_buffer_to_golden",
|
||||
frame_hdr->copy_buffer_to_golden);
|
||||
}
|
||||
if (!frame_hdr->refresh_alternate_frame) {
|
||||
g_print (" %-32s : %d\n", "copy_buffer_to_alternate",
|
||||
frame_hdr->copy_buffer_to_alternate);
|
||||
}
|
||||
g_print (" %-32s : %d\n", "sign_bias_golden", frame_hdr->sign_bias_golden);
|
||||
g_print (" %-32s : %d\n", "sign_bias_alternate",
|
||||
frame_hdr->sign_bias_alternate);
|
||||
g_print (" %-32s : %d\n", "refresh_entropy_probs",
|
||||
frame_hdr->refresh_entropy_probs);
|
||||
g_print (" %-32s : %d\n", "refresh_last", frame_hdr->refresh_last);
|
||||
}
|
||||
|
||||
g_print (" %-32s : %d\n", "mb_no_skip_coeff", frame_hdr->mb_no_skip_coeff);
|
||||
if (frame_hdr->mb_no_skip_coeff) {
|
||||
g_print (" %-32s : %d\n", "prob_skip_false", frame_hdr->prob_skip_false);
|
||||
}
|
||||
|
||||
if (!frame_hdr->key_frame) {
|
||||
g_print (" %-32s : %d\n", "prob_intra", frame_hdr->prob_intra);
|
||||
g_print (" %-32s : %d\n", "prob_last", frame_hdr->prob_last);
|
||||
g_print (" %-32s : %d\n", "prob_gf", frame_hdr->prob_gf);
|
||||
}
|
||||
|
||||
print_quant_indices (&frame_hdr->quant_indices);
|
||||
print_mv_probs (&frame_hdr->mv_probs);
|
||||
print_mode_probs (&frame_hdr->mode_probs);
|
||||
}
|
||||
|
||||
gint
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
guint8 buf[(VP8_FRAME_HDR_SIZE + 7) / 8];
|
||||
IVFFileHdr ivf_file_hdr;
|
||||
IVFFrameHdr ivf_frame_hdr;
|
||||
GstVp8Parser parser;
|
||||
GstVp8FrameHdr frame_hdr;
|
||||
guint hdr_size, frame_num = 0;
|
||||
|
||||
g_assert (sizeof (buf) >= IVF_FILE_HDR_SIZE);
|
||||
g_assert (sizeof (buf) >= IVF_FRAME_HDR_SIZE);
|
||||
|
||||
if (argc < 2) {
|
||||
g_printerr ("Usage: %s <IVF file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fp = fopen (argv[1], "r");
|
||||
if (!fp) {
|
||||
g_printerr ("failed to open IVF file (%s)\n", argv[1]);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (fread (buf, IVF_FILE_HDR_SIZE, 1, fp) != 1) {
|
||||
g_printerr ("failed to read IVF header\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!parse_ivf_file_header (&ivf_file_hdr, buf, IVF_FILE_HDR_SIZE)) {
|
||||
g_printerr ("failed to parse IVF header\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
gst_vp8_parser_init (&parser);
|
||||
while (fread (buf, IVF_FRAME_HDR_SIZE, 1, fp) == 1) {
|
||||
if (!parse_ivf_frame_header (&ivf_frame_hdr, buf, IVF_FRAME_HDR_SIZE)) {
|
||||
g_printerr ("fail to parse IVF frame header\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_print ("Frame #%d @ offset %lu\n", frame_num, (gulong) ftell (fp));
|
||||
hdr_size = MIN (sizeof (buf), ivf_frame_hdr.frame_size);
|
||||
if (fread (buf, hdr_size, 1, fp) != 1) {
|
||||
g_printerr ("failed to read VP8 frame header\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
hdr_size = ivf_frame_hdr.frame_size - hdr_size;
|
||||
if (hdr_size > 0 && fseek (fp, hdr_size, SEEK_CUR) != 0) {
|
||||
g_printerr ("failed to skip frame data (%u bytes): %s\n",
|
||||
ivf_frame_hdr.frame_size, strerror (errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
memset (&frame_hdr, 0, sizeof (frame_hdr));
|
||||
if (gst_vp8_parser_parse_frame_header (&parser, &frame_hdr, buf,
|
||||
ivf_frame_hdr.frame_size) != GST_VP8_PARSER_OK) {
|
||||
g_printerr ("failed to parse frame header\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
print_frame_header (&frame_hdr);
|
||||
print_segmentation (&parser.segmentation);
|
||||
print_mb_lf_adjustments (&parser.mb_lf_adjust);
|
||||
g_print ("\n");
|
||||
|
||||
frame_num++;
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (fp)
|
||||
fclose (fp);
|
||||
return 1;
|
||||
}
|
Loading…
Reference in a new issue