| /* | |
| * gstav12json.c - AV1 parsed bistream to json | |
| * | |
| * Copyright (C) 2023 Collabora | |
| * Author: Benjamin Gaignard <benjamin.gaignard@collabora.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:element-av12json | |
| * @title: av12json | |
| * | |
| * Convert AV1 bitstream parameters to JSON formated text. | |
| * | |
| * ## Example launch line | |
| * ``` | |
| * gst-launch-1.0 filesrc location=/path/to/av1/file ! parsebin ! av12json ! filesink location=/path/to/json/file | |
| * ``` | |
| * | |
| * Since: 1.24 | |
| */ | |
| #ifdef HAVE_CONFIG_H | |
| #include <config.h> | |
| #endif | |
| #include <gst/base/base.h> | |
| #include <json-glib/json-glib.h> | |
| #include "gstav12json.h" | |
| GST_DEBUG_CATEGORY (gst_av1_2_json_debug); | |
| #define GST_CAT_DEFAULT gst_av1_2_json_debug | |
| struct _GstAV12json | |
| { | |
| GstElement parent; | |
| GstPad *sinkpad, *srcpad; | |
| GstAV1Parser *parser; | |
| gboolean use_annex_b; | |
| JsonObject *json; | |
| }; | |
| static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", | |
| GST_PAD_SINK, | |
| GST_PAD_ALWAYS, | |
| GST_STATIC_CAPS ("video/x-av1") | |
| ); | |
| static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", | |
| GST_PAD_SRC, | |
| GST_PAD_ALWAYS, | |
| GST_STATIC_CAPS ("text/x-json,format=av1")); | |
| G_DEFINE_TYPE_WITH_CODE (GstAV12json, gst_av1_2_json, | |
| GST_TYPE_ELEMENT, | |
| GST_DEBUG_CATEGORY_INIT (gst_av1_2_json_debug, "av12json", 0, | |
| "AV1 to json")); | |
| static void | |
| gst_av1_2_json_finalize (GObject * object) | |
| { | |
| GstAV12json *self = GST_AV1_2_JSON (object); | |
| gst_av1_parser_free (self->parser); | |
| json_object_unref (self->json); | |
| } | |
| static gchar * | |
| get_string_from_json_object (JsonObject * object) | |
| { | |
| JsonNode *root; | |
| JsonGenerator *generator; | |
| gchar *text; | |
| /* Make it the root node */ | |
| root = json_node_init_object (json_node_alloc (), object); | |
| generator = json_generator_new (); | |
| json_generator_set_indent (generator, 2); | |
| json_generator_set_indent_char (generator, ' '); | |
| json_generator_set_pretty (generator, TRUE); | |
| json_generator_set_root (generator, root); | |
| text = json_generator_to_data (generator, NULL); | |
| /* Release everything */ | |
| g_object_unref (generator); | |
| json_node_free (root); | |
| return text; | |
| } | |
| static void | |
| gst_av1_2_json_sequence_header (GstAV12json * self, | |
| GstAV1SequenceHeaderOBU * seq_header) | |
| { | |
| JsonObject *json = self->json; | |
| JsonObject *hdr = json_object_new (); | |
| JsonArray *operating_points; | |
| JsonObject *color_config; | |
| guint i; | |
| json_object_set_int_member (hdr, "seq profile", seq_header->seq_profile); | |
| json_object_set_boolean_member (hdr, "still picture", | |
| seq_header->still_picture); | |
| json_object_set_int_member (hdr, "reduced still picture header", | |
| seq_header->reduced_still_picture_header); | |
| json_object_set_int_member (hdr, "frame width bits minus 1", | |
| seq_header->frame_width_bits_minus_1); | |
| json_object_set_int_member (hdr, "frame height bits minus 1", | |
| seq_header->frame_height_bits_minus_1); | |
| json_object_set_int_member (hdr, "max frame width minus 1", | |
| seq_header->max_frame_width_minus_1); | |
| json_object_set_int_member (hdr, "max frame height minus 1", | |
| seq_header->max_frame_height_minus_1); | |
| json_object_set_boolean_member (hdr, "frame id numbers present flag", | |
| seq_header->frame_id_numbers_present_flag); | |
| json_object_set_int_member (hdr, "delta frame id length minus 2", | |
| seq_header->delta_frame_id_length_minus_2); | |
| json_object_set_int_member (hdr, "additional frame id length minus 1", | |
| seq_header->additional_frame_id_length_minus_1); | |
| json_object_set_boolean_member (hdr, "use 128x128 superblock", | |
| seq_header->use_128x128_superblock); | |
| json_object_set_boolean_member (hdr, "enable filter intra", | |
| seq_header->enable_filter_intra); | |
| json_object_set_boolean_member (hdr, "enable intra edge filter", | |
| seq_header->enable_intra_edge_filter); | |
| json_object_set_boolean_member (hdr, "enable interintra compound", | |
| seq_header->enable_interintra_compound); | |
| json_object_set_boolean_member (hdr, "enable masked compound", | |
| seq_header->enable_masked_compound); | |
| json_object_set_boolean_member (hdr, "enable warped motion", | |
| seq_header->enable_warped_motion); | |
| json_object_set_boolean_member (hdr, "enable order hint", | |
| seq_header->enable_order_hint); | |
| json_object_set_boolean_member (hdr, "enable dual filter", | |
| seq_header->enable_dual_filter); | |
| json_object_set_boolean_member (hdr, "enable jnt comp", | |
| seq_header->enable_jnt_comp); | |
| json_object_set_boolean_member (hdr, "enable ref frame mvs", | |
| seq_header->enable_ref_frame_mvs); | |
| json_object_set_boolean_member (hdr, "seq choose screen content tools", | |
| seq_header->seq_choose_screen_content_tools); | |
| json_object_set_int_member (hdr, "seq force screen content tools", | |
| seq_header->seq_force_screen_content_tools); | |
| json_object_set_boolean_member (hdr, "seq choose integer mv", | |
| seq_header->seq_choose_integer_mv); | |
| json_object_set_int_member (hdr, "seq force integer mv", | |
| seq_header->seq_force_integer_mv); | |
| json_object_set_int_member (hdr, "order hint bits minus 1", | |
| seq_header->order_hint_bits_minus_1); | |
| json_object_set_boolean_member (hdr, "enable superres", | |
| seq_header->enable_superres); | |
| json_object_set_boolean_member (hdr, "enable cdef", seq_header->enable_cdef); | |
| json_object_set_boolean_member (hdr, "enable restoration", | |
| seq_header->enable_restoration); | |
| json_object_set_int_member (hdr, "film grain params present", | |
| seq_header->film_grain_params_present); | |
| json_object_set_int_member (hdr, "operating points cnt minus 1", | |
| seq_header->operating_points_cnt_minus_1); | |
| operating_points = json_array_new (); | |
| for (i = 0; i < seq_header->operating_points_cnt_minus_1 + 1; i++) { | |
| JsonObject *operating_point = json_object_new (); | |
| json_object_set_int_member (operating_point, "seq level idx", | |
| seq_header->operating_points[i].seq_level_idx); | |
| json_object_set_int_member (operating_point, "seq tier", | |
| seq_header->operating_points[i].seq_tier); | |
| json_object_set_int_member (operating_point, "idc", | |
| seq_header->operating_points[i].idc); | |
| json_object_set_boolean_member (operating_point, | |
| "decoder model present for this op", | |
| seq_header->operating_points[i].decoder_model_present_for_this_op); | |
| json_object_set_int_member (operating_point, "decoder buffer delay", | |
| seq_header->operating_points[i].decoder_buffer_delay); | |
| json_object_set_int_member (operating_point, "encoder buffer delay", | |
| seq_header->operating_points[i].encoder_buffer_delay); | |
| json_object_set_boolean_member (operating_point, "low delay mode flag", | |
| seq_header->operating_points[i].low_delay_mode_flag); | |
| json_object_set_boolean_member (operating_point, | |
| "initial display delay present for this op", | |
| seq_header-> | |
| operating_points[i].initial_display_delay_present_for_this_op); | |
| json_object_set_int_member (operating_point, | |
| "initial display delay minus 1", | |
| seq_header->operating_points[i].initial_display_delay_minus_1); | |
| json_array_add_object_element (operating_points, operating_point); | |
| } | |
| json_object_set_array_member (hdr, "operating points", operating_points); | |
| json_object_set_boolean_member (hdr, "decoder model info present flag", | |
| seq_header->decoder_model_info_present_flag); | |
| if (seq_header->decoder_model_info_present_flag) { | |
| JsonObject *decoder_model_info = json_object_new (); | |
| json_object_set_int_member (decoder_model_info, | |
| "buffer delay length minus 1", | |
| seq_header->decoder_model_info.buffer_delay_length_minus_1); | |
| json_object_set_int_member (decoder_model_info, | |
| "num units in decoding tick", | |
| seq_header->decoder_model_info.num_units_in_decoding_tick); | |
| json_object_set_int_member (decoder_model_info, | |
| "buffer removal time length minus 1", | |
| seq_header->decoder_model_info.buffer_removal_time_length_minus_1); | |
| json_object_set_int_member (decoder_model_info, | |
| "frame presentation time length minus 1", | |
| seq_header->decoder_model_info.frame_presentation_time_length_minus_1); | |
| json_object_set_object_member (hdr, "decoder model info", | |
| decoder_model_info); | |
| } | |
| json_object_set_int_member (hdr, "initial display delay present flag", | |
| seq_header->initial_display_delay_present_flag); | |
| json_object_set_boolean_member (hdr, "timing info present flag", | |
| seq_header->timing_info_present_flag); | |
| if (seq_header->timing_info_present_flag) { | |
| JsonObject *timing_info = json_object_new (); | |
| json_object_set_int_member (timing_info, "num units in display tick", | |
| seq_header->timing_info.num_units_in_display_tick); | |
| json_object_set_int_member (timing_info, "time scale", | |
| seq_header->timing_info.time_scale); | |
| json_object_set_boolean_member (timing_info, "equal picture interval", | |
| seq_header->timing_info.equal_picture_interval); | |
| json_object_set_int_member (timing_info, "num ticks per picture minus 1", | |
| seq_header->timing_info.num_ticks_per_picture_minus_1); | |
| json_object_set_object_member (hdr, "timing info", timing_info); | |
| } | |
| color_config = json_object_new (); | |
| json_object_set_boolean_member (color_config, "high bitdepth", | |
| seq_header->color_config.high_bitdepth); | |
| json_object_set_boolean_member (color_config, "twelve bit", | |
| seq_header->color_config.twelve_bit); | |
| json_object_set_boolean_member (color_config, "mono chrome", | |
| seq_header->color_config.mono_chrome); | |
| json_object_set_boolean_member (color_config, | |
| "color description present flag", | |
| seq_header->color_config.color_description_present_flag); | |
| json_object_set_int_member (color_config, "color primaries", | |
| seq_header->color_config.color_primaries); | |
| json_object_set_int_member (color_config, "transfer characteristics", | |
| seq_header->color_config.transfer_characteristics); | |
| json_object_set_int_member (color_config, "matrix coefficients", | |
| seq_header->color_config.matrix_coefficients); | |
| json_object_set_boolean_member (color_config, "color range", | |
| seq_header->color_config.color_range); | |
| json_object_set_int_member (color_config, "subsampling x", | |
| seq_header->color_config.subsampling_x); | |
| json_object_set_int_member (color_config, "subsampling y", | |
| seq_header->color_config.subsampling_y); | |
| json_object_set_int_member (color_config, "chroma sample position", | |
| seq_header->color_config.chroma_sample_position); | |
| json_object_set_boolean_member (color_config, "separate uv delta q", | |
| seq_header->color_config.separate_uv_delta_q); | |
| json_object_set_object_member (hdr, "color config", color_config); | |
| json_object_set_int_member (hdr, "order hint bits", | |
| seq_header->order_hint_bits); | |
| json_object_set_int_member (hdr, "bit depth", seq_header->bit_depth); | |
| json_object_set_int_member (hdr, "num planes", seq_header->num_planes); | |
| json_object_set_object_member (json, "sequence header", hdr); | |
| } | |
| static void | |
| gst_av1_2_json_frame_header (GstAV12json * self, | |
| GstAV1FrameHeaderOBU * frame_header) | |
| { | |
| JsonObject *json = self->json; | |
| JsonArray *buffer_removal_time, *ref_order_hint, *ref_frame_idx, | |
| *loop_filter_level, *loop_filter_ref_deltas, *loop_filter_mode_deltas, | |
| *feature_enabled, *feature_data, *width_in_sbs_minus_1, | |
| *height_in_sbs_minus_1, *mi_col_starts, *mi_row_starts, | |
| *cdef_y_pri_strength, *cdef_y_sec_strength, *cdef_uv_pri_strength, | |
| *cdef_uv_sec_strength, *frame_restoration_type, *loop_restoration_size, | |
| *is_global, *is_rot_zoom, *is_translation, *gm_params, *gm_type, *invalid, | |
| *point_y_value, *point_y_scaling, *point_cb_value, *point_cb_scaling, | |
| *point_cr_value, *point_cr_scaling, *ar_coeffs_y_plus_128, | |
| *ar_coeffs_cb_plus_128, *ar_coeffs_cr_plus_128, *order_hints, | |
| *ref_frame_sign_bias, *lossless_array, *seg_qm_level, *skip_mode_frame; | |
| JsonObject *hdr = json_object_new (); | |
| JsonObject *loop_filter_params, *quantization_params, *segmentation_params, | |
| *tile_info, *cdef_params, *loop_restoration_params, *global_motion_params, | |
| *film_grain_params; | |
| guint i, j; | |
| json_object_set_boolean_member (hdr, "show existing frame", | |
| frame_header->show_existing_frame); | |
| json_object_set_int_member (hdr, "frame to show map idx", | |
| frame_header->frame_to_show_map_idx); | |
| json_object_set_int_member (hdr, "frame presentation time", | |
| frame_header->frame_presentation_time); | |
| json_object_set_int_member (hdr, "tu presentation delay", | |
| frame_header->tu_presentation_delay); | |
| json_object_set_int_member (hdr, "display frame id", | |
| frame_header->display_frame_id); | |
| switch (frame_header->frame_type) { | |
| case GST_AV1_KEY_FRAME: | |
| json_object_set_string_member (hdr, "frame type", "key frame"); | |
| break; | |
| case GST_AV1_INTER_FRAME: | |
| json_object_set_string_member (hdr, "frame type", "inter frame"); | |
| break; | |
| case GST_AV1_INTRA_ONLY_FRAME: | |
| json_object_set_string_member (hdr, "frame type", "intra only frame"); | |
| break; | |
| case GST_AV1_SWITCH_FRAME: | |
| json_object_set_string_member (hdr, "frame type", "switch frame"); | |
| break; | |
| } | |
| json_object_set_boolean_member (hdr, "show frame", frame_header->show_frame); | |
| json_object_set_boolean_member (hdr, "showable frame", | |
| frame_header->showable_frame); | |
| json_object_set_boolean_member (hdr, "error resilient mode", | |
| frame_header->error_resilient_mode); | |
| json_object_set_boolean_member (hdr, "disable cdf update", | |
| frame_header->disable_cdf_update); | |
| json_object_set_int_member (hdr, "allow screen content tools", | |
| frame_header->allow_screen_content_tools); | |
| json_object_set_boolean_member (hdr, "force integer_mv", | |
| frame_header->force_integer_mv); | |
| json_object_set_int_member (hdr, "current frame id", | |
| frame_header->current_frame_id); | |
| json_object_set_boolean_member (hdr, "frame size override flag", | |
| frame_header->frame_size_override_flag); | |
| json_object_set_int_member (hdr, "order hint", frame_header->order_hint); | |
| json_object_set_int_member (hdr, "primary ref_frame", | |
| frame_header->primary_ref_frame); | |
| json_object_set_boolean_member (hdr, "buffer removal time present flag", | |
| frame_header->buffer_removal_time_present_flag); | |
| buffer_removal_time = json_array_new (); | |
| for (i = 0; i < GST_AV1_MAX_OPERATING_POINTS; i++) | |
| json_array_add_int_element (buffer_removal_time, | |
| frame_header->buffer_removal_time[i]); | |
| json_object_set_array_member (hdr, "buffer removal time", | |
| buffer_removal_time); | |
| json_object_set_int_member (hdr, "refresh frame flags", | |
| frame_header->refresh_frame_flags); | |
| ref_order_hint = json_array_new (); | |
| for (i = 0; i < GST_AV1_NUM_REF_FRAMES; i++) | |
| json_array_add_int_element (ref_order_hint, | |
| frame_header->ref_order_hint[i]); | |
| json_object_set_array_member (hdr, "ref order hint", ref_order_hint); | |
| json_object_set_boolean_member (hdr, "allow intrabc", | |
| frame_header->allow_intrabc); | |
| json_object_set_boolean_member (hdr, "frame refs short signaling", | |
| frame_header->frame_refs_short_signaling); | |
| json_object_set_int_member (hdr, "last frame idx", | |
| frame_header->last_frame_idx); | |
| json_object_set_int_member (hdr, "gold frame idx", | |
| frame_header->gold_frame_idx); | |
| ref_frame_idx = json_array_new (); | |
| for (i = 0; i < GST_AV1_REFS_PER_FRAME; i++) | |
| json_array_add_int_element (ref_frame_idx, frame_header->ref_frame_idx[i]); | |
| json_object_set_array_member (hdr, "ref frame idx", ref_frame_idx); | |
| json_object_set_boolean_member (hdr, "allow high precision mv", | |
| frame_header->allow_high_precision_mv); | |
| json_object_set_boolean_member (hdr, "is motion mode switchable", | |
| frame_header->is_motion_mode_switchable); | |
| json_object_set_boolean_member (hdr, "use ref frame mvs", | |
| frame_header->use_ref_frame_mvs); | |
| json_object_set_boolean_member (hdr, "disable frame end update cdf", | |
| frame_header->disable_frame_end_update_cdf); | |
| json_object_set_boolean_member (hdr, "allow warped motion", | |
| frame_header->allow_warped_motion); | |
| json_object_set_boolean_member (hdr, "reduced tx set", | |
| frame_header->reduced_tx_set); | |
| json_object_set_boolean_member (hdr, "render and frame size different", | |
| frame_header->render_and_frame_size_different); | |
| json_object_set_boolean_member (hdr, "use superres", | |
| frame_header->use_superres); | |
| json_object_set_boolean_member (hdr, "is filter switchable", | |
| frame_header->is_filter_switchable); | |
| json_object_set_int_member (hdr, "interpolation filter", | |
| frame_header->interpolation_filter); | |
| loop_filter_params = json_object_new (); | |
| loop_filter_level = json_array_new (); | |
| for (i = 0; i < 4; i++) | |
| json_array_add_int_element (loop_filter_level, | |
| frame_header->loop_filter_params.loop_filter_level[i]); | |
| json_object_set_array_member (loop_filter_params, "loop filter level", | |
| loop_filter_level); | |
| json_object_set_int_member (loop_filter_params, "loop filter sharpness", | |
| frame_header->loop_filter_params.loop_filter_sharpness); | |
| json_object_set_boolean_member (loop_filter_params, | |
| "loop filter delta enabled", | |
| frame_header->loop_filter_params.loop_filter_delta_enabled); | |
| json_object_set_boolean_member (loop_filter_params, | |
| "loop filter delta update", | |
| frame_header->loop_filter_params.loop_filter_delta_update); | |
| loop_filter_ref_deltas = json_array_new (); | |
| for (i = 0; i < GST_AV1_TOTAL_REFS_PER_FRAME; i++) | |
| json_array_add_int_element (loop_filter_ref_deltas, | |
| frame_header->loop_filter_params.loop_filter_ref_deltas[i]); | |
| json_object_set_array_member (loop_filter_params, "loop filter ref deltas", | |
| loop_filter_ref_deltas); | |
| loop_filter_mode_deltas = json_array_new (); | |
| for (i = 0; i < 2; i++) | |
| json_array_add_int_element (loop_filter_mode_deltas, | |
| frame_header->loop_filter_params.loop_filter_mode_deltas[i]); | |
| json_object_set_array_member (loop_filter_params, "loop filter mode deltas", | |
| loop_filter_mode_deltas); | |
| json_object_set_boolean_member (loop_filter_params, "delta lf present", | |
| frame_header->loop_filter_params.delta_lf_present); | |
| json_object_set_int_member (loop_filter_params, "delta lf res", | |
| frame_header->loop_filter_params.delta_lf_res); | |
| json_object_set_int_member (loop_filter_params, "delta lf multi", | |
| frame_header->loop_filter_params.delta_lf_multi); | |
| json_object_set_object_member (hdr, "loop filter params", loop_filter_params); | |
| quantization_params = json_object_new (); | |
| json_object_set_int_member (quantization_params, "base q idx", | |
| frame_header->quantization_params.base_q_idx); | |
| json_object_set_boolean_member (quantization_params, "diff uv delta", | |
| frame_header->quantization_params.diff_uv_delta); | |
| json_object_set_boolean_member (quantization_params, "using qmatrix", | |
| frame_header->quantization_params.using_qmatrix); | |
| json_object_set_int_member (quantization_params, "qm y", | |
| frame_header->quantization_params.qm_y); | |
| json_object_set_int_member (quantization_params, "qm u", | |
| frame_header->quantization_params.qm_u); | |
| json_object_set_int_member (quantization_params, "qm v", | |
| frame_header->quantization_params.qm_v); | |
| json_object_set_boolean_member (quantization_params, "delta q present", | |
| frame_header->quantization_params.delta_q_present); | |
| json_object_set_int_member (quantization_params, "delta q res", | |
| frame_header->quantization_params.delta_q_res); | |
| json_object_set_int_member (quantization_params, "delta q y dc", | |
| frame_header->quantization_params.delta_q_y_dc); | |
| json_object_set_int_member (quantization_params, "delta q u dc", | |
| frame_header->quantization_params.delta_q_u_dc); | |
| json_object_set_int_member (quantization_params, "delta q u ac", | |
| frame_header->quantization_params.delta_q_u_ac); | |
| json_object_set_int_member (quantization_params, "delta q v dc", | |
| frame_header->quantization_params.delta_q_v_dc); | |
| json_object_set_int_member (quantization_params, "delta q v ac", | |
| frame_header->quantization_params.delta_q_v_ac); | |
| json_object_set_object_member (hdr, "quantization params", | |
| quantization_params); | |
| segmentation_params = json_object_new (); | |
| json_object_set_boolean_member (segmentation_params, "segmentation enabled", | |
| frame_header->segmentation_params.segmentation_enabled); | |
| json_object_set_int_member (segmentation_params, "segmentation update map", | |
| frame_header->segmentation_params.segmentation_update_map); | |
| json_object_set_int_member (segmentation_params, | |
| "segmentation temporal update", | |
| frame_header->segmentation_params.segmentation_temporal_update); | |
| json_object_set_int_member (segmentation_params, "segmentation update data", | |
| frame_header->segmentation_params.segmentation_update_data); | |
| feature_enabled = json_array_new (); | |
| feature_data = json_array_new (); | |
| for (i = 0; i < GST_AV1_MAX_SEGMENTS; i++) { | |
| for (j = 0; j < GST_AV1_SEG_LVL_MAX; j++) { | |
| json_array_add_int_element (feature_enabled, | |
| frame_header->segmentation_params.feature_enabled[i][j]); | |
| json_array_add_int_element (feature_data, | |
| frame_header->segmentation_params.feature_data[i][j]); | |
| } | |
| } | |
| json_object_set_array_member (segmentation_params, "feature enabled", | |
| feature_enabled); | |
| json_object_set_array_member (segmentation_params, "feature data", | |
| feature_data); | |
| json_object_set_int_member (segmentation_params, "seg id pre skip", | |
| frame_header->segmentation_params.seg_id_pre_skip); | |
| json_object_set_int_member (segmentation_params, "last active seg id", | |
| frame_header->segmentation_params.last_active_seg_id); | |
| json_object_set_object_member (hdr, "segmentation params", | |
| segmentation_params); | |
| tile_info = json_object_new (); | |
| json_object_set_int_member (tile_info, "uniform tile spacing flag", | |
| frame_header->tile_info.uniform_tile_spacing_flag); | |
| json_object_set_int_member (tile_info, "increment tile rows log2", | |
| frame_header->tile_info.increment_tile_rows_log2); | |
| width_in_sbs_minus_1 = json_array_new (); | |
| height_in_sbs_minus_1 = json_array_new (); | |
| for (i = 0; i < GST_AV1_MAX_TILE_COLS; i++) { | |
| json_array_add_int_element (width_in_sbs_minus_1, | |
| frame_header->tile_info.width_in_sbs_minus_1[i]); | |
| json_array_add_int_element (height_in_sbs_minus_1, | |
| frame_header->tile_info.height_in_sbs_minus_1[i]); | |
| } | |
| json_object_set_array_member (tile_info, "width in sbs minus 1", | |
| width_in_sbs_minus_1); | |
| json_object_set_array_member (tile_info, "height in sbs minus 1", | |
| height_in_sbs_minus_1); | |
| json_object_set_int_member (tile_info, "tile size bytes minus 1", | |
| frame_header->tile_info.tile_size_bytes_minus_1); | |
| json_object_set_int_member (tile_info, "context update tile id", | |
| frame_header->tile_info.context_update_tile_id); | |
| mi_col_starts = json_array_new (); | |
| mi_row_starts = json_array_new (); | |
| for (i = 0; i < GST_AV1_MAX_TILE_COLS + 1; i++) { | |
| json_array_add_int_element (mi_col_starts, | |
| frame_header->tile_info.mi_col_starts[i]); | |
| json_array_add_int_element (mi_row_starts, | |
| frame_header->tile_info.mi_row_starts[i]); | |
| } | |
| json_object_set_array_member (tile_info, "mi col starts", mi_col_starts); | |
| json_object_set_array_member (tile_info, "mi row starts", mi_row_starts); | |
| json_object_set_int_member (tile_info, "tile cols log2", | |
| frame_header->tile_info.tile_cols_log2); | |
| json_object_set_int_member (tile_info, "tile cols", | |
| frame_header->tile_info.tile_cols); | |
| json_object_set_int_member (tile_info, "tile rows log2", | |
| frame_header->tile_info.tile_rows_log2); | |
| json_object_set_int_member (tile_info, "tile rows", | |
| frame_header->tile_info.tile_rows); | |
| json_object_set_int_member (tile_info, "tile size bytes", | |
| frame_header->tile_info.tile_size_bytes); | |
| json_object_set_object_member (hdr, "tile_info", tile_info); | |
| cdef_params = json_object_new (); | |
| json_object_set_int_member (cdef_params, "cdef damping", | |
| frame_header->cdef_params.cdef_damping); | |
| json_object_set_int_member (cdef_params, "cdef bits", | |
| frame_header->cdef_params.cdef_bits); | |
| cdef_y_pri_strength = json_array_new (); | |
| cdef_y_sec_strength = json_array_new (); | |
| cdef_uv_pri_strength = json_array_new (); | |
| cdef_uv_sec_strength = json_array_new (); | |
| for (i = 0; i < GST_AV1_CDEF_MAX; i++) { | |
| json_array_add_int_element (cdef_y_pri_strength, | |
| frame_header->cdef_params.cdef_y_pri_strength[i]); | |
| json_array_add_int_element (cdef_y_sec_strength, | |
| frame_header->cdef_params.cdef_y_sec_strength[i]); | |
| json_array_add_int_element (cdef_uv_pri_strength, | |
| frame_header->cdef_params.cdef_uv_pri_strength[i]); | |
| json_array_add_int_element (cdef_uv_sec_strength, | |
| frame_header->cdef_params.cdef_uv_sec_strength[i]); | |
| } | |
| json_object_set_array_member (cdef_params, "cdef y pri strength", | |
| cdef_y_pri_strength); | |
| json_object_set_array_member (cdef_params, "cdef y sec strength", | |
| cdef_y_sec_strength); | |
| json_object_set_array_member (cdef_params, "cdef uv pri_strength", | |
| cdef_uv_pri_strength); | |
| json_object_set_array_member (cdef_params, "cdef uv sec_strength", | |
| cdef_uv_sec_strength); | |
| json_object_set_object_member (hdr, "cdef params", cdef_params); | |
| loop_restoration_params = json_object_new (); | |
| json_object_set_int_member (loop_restoration_params, "lr unit shift", | |
| frame_header->loop_restoration_params.lr_unit_shift); | |
| json_object_set_int_member (loop_restoration_params, "lr uv shift", | |
| frame_header->loop_restoration_params.lr_uv_shift); | |
| frame_restoration_type = json_array_new (); | |
| loop_restoration_size = json_array_new (); | |
| for (i = 0; i < GST_AV1_MAX_NUM_PLANES; i++) { | |
| json_array_add_int_element (frame_restoration_type, | |
| frame_header->loop_restoration_params.frame_restoration_type[i]); | |
| json_array_add_int_element (loop_restoration_size, | |
| frame_header->loop_restoration_params.loop_restoration_size[i]); | |
| } | |
| json_object_set_array_member (loop_restoration_params, | |
| "frame restoration type", frame_restoration_type); | |
| json_object_set_array_member (loop_restoration_params, | |
| "loop restoration size", loop_restoration_size); | |
| json_object_set_int_member (loop_restoration_params, "uses lr", | |
| frame_header->loop_restoration_params.uses_lr); | |
| json_object_set_object_member (hdr, "loop restoration params", | |
| loop_restoration_params); | |
| json_object_set_boolean_member (hdr, "tx mode select", | |
| frame_header->tx_mode_select); | |
| json_object_set_boolean_member (hdr, "skip mode present", | |
| frame_header->skip_mode_present); | |
| json_object_set_boolean_member (hdr, "reference select", | |
| frame_header->reference_select); | |
| global_motion_params = json_object_new (); | |
| is_global = json_array_new (); | |
| is_rot_zoom = json_array_new (); | |
| is_translation = json_array_new (); | |
| gm_params = json_array_new (); | |
| gm_type = json_array_new (); | |
| invalid = json_array_new (); | |
| for (i = 0; i < GST_AV1_NUM_REF_FRAMES; i++) { | |
| json_array_add_boolean_element (is_global, | |
| frame_header->global_motion_params.is_global[i]); | |
| json_array_add_boolean_element (is_rot_zoom, | |
| frame_header->global_motion_params.is_rot_zoom[i]); | |
| json_array_add_boolean_element (is_translation, | |
| frame_header->global_motion_params.is_translation[i]); | |
| for (j = 0; j < 6; j++) | |
| json_array_add_int_element (gm_params, | |
| frame_header->global_motion_params.gm_params[i][j]); | |
| json_array_add_int_element (gm_type, | |
| frame_header->global_motion_params.gm_type[i]); | |
| json_array_add_boolean_element (invalid, | |
| frame_header->global_motion_params.invalid[i]); | |
| } | |
| json_object_set_array_member (global_motion_params, "is global", is_global); | |
| json_object_set_array_member (global_motion_params, "is rot zoom", | |
| is_rot_zoom); | |
| json_object_set_array_member (global_motion_params, "is translation", | |
| is_translation); | |
| json_object_set_array_member (global_motion_params, "gm params", gm_params); | |
| json_object_set_array_member (global_motion_params, "gm type", gm_type); | |
| json_object_set_array_member (global_motion_params, "invalid", invalid); | |
| json_object_set_object_member (hdr, "global motion params", | |
| global_motion_params); | |
| film_grain_params = json_object_new (); | |
| json_object_set_boolean_member (film_grain_params, "apply grain", | |
| frame_header->film_grain_params.apply_grain); | |
| json_object_set_int_member (film_grain_params, "grain seed", | |
| frame_header->film_grain_params.grain_seed); | |
| json_object_set_boolean_member (film_grain_params, "update grain", | |
| frame_header->film_grain_params.update_grain); | |
| json_object_set_int_member (film_grain_params, "film grain params ref idx", | |
| frame_header->film_grain_params.film_grain_params_ref_idx); | |
| json_object_set_int_member (film_grain_params, "num y points", | |
| frame_header->film_grain_params.num_y_points); | |
| point_y_value = json_array_new (); | |
| point_y_scaling = json_array_new (); | |
| for (i = 0; i < GST_AV1_MAX_NUM_Y_POINTS; i++) { | |
| json_array_add_int_element (point_y_value, | |
| frame_header->film_grain_params.point_y_value[i]); | |
| json_array_add_int_element (point_y_scaling, | |
| frame_header->film_grain_params.point_y_scaling[i]); | |
| } | |
| json_object_set_array_member (film_grain_params, "point y value", | |
| point_y_value); | |
| json_object_set_array_member (film_grain_params, "point y scaling", | |
| point_y_scaling); | |
| json_object_set_int_member (film_grain_params, "chroma scaling from luma", | |
| frame_header->film_grain_params.chroma_scaling_from_luma); | |
| json_object_set_int_member (film_grain_params, "num cb points", | |
| frame_header->film_grain_params.num_cb_points); | |
| point_cb_value = json_array_new (); | |
| point_cb_scaling = json_array_new (); | |
| for (i = 0; i < GST_AV1_MAX_NUM_CB_POINTS; i++) { | |
| json_array_add_int_element (point_cb_value, | |
| frame_header->film_grain_params.point_cb_value[i]); | |
| json_array_add_int_element (point_cb_scaling, | |
| frame_header->film_grain_params.point_cb_scaling[i]); | |
| } | |
| json_object_set_array_member (film_grain_params, "point cb value", | |
| point_cb_value); | |
| json_object_set_array_member (film_grain_params, "point cb scaling", | |
| point_cb_scaling); | |
| json_object_set_int_member (film_grain_params, "num cr points", | |
| frame_header->film_grain_params.num_cr_points); | |
| point_cr_value = json_array_new (); | |
| point_cr_scaling = json_array_new (); | |
| for (i = 0; i < GST_AV1_MAX_NUM_CR_POINTS; i++) { | |
| json_array_add_int_element (point_cr_value, | |
| frame_header->film_grain_params.point_cr_value[i]); | |
| json_array_add_int_element (point_cr_scaling, | |
| frame_header->film_grain_params.point_cr_scaling[i]); | |
| } | |
| json_object_set_array_member (film_grain_params, "point cr value", | |
| point_cr_value); | |
| json_object_set_array_member (film_grain_params, "point cr scaling", | |
| point_cr_scaling); | |
| json_object_set_int_member (film_grain_params, "grain scaling minus 8", | |
| frame_header->film_grain_params.grain_scaling_minus_8); | |
| json_object_set_int_member (film_grain_params, "ar coeff lag", | |
| frame_header->film_grain_params.ar_coeff_lag); | |
| ar_coeffs_y_plus_128 = json_array_new (); | |
| ar_coeffs_cb_plus_128 = json_array_new (); | |
| ar_coeffs_cr_plus_128 = json_array_new (); | |
| for (i = 0; i < GST_AV1_MAX_NUM_POS_LUMA; i++) { | |
| json_array_add_int_element (ar_coeffs_y_plus_128, | |
| frame_header->film_grain_params.ar_coeffs_y_plus_128[i]); | |
| json_array_add_int_element (ar_coeffs_cb_plus_128, | |
| frame_header->film_grain_params.ar_coeffs_cb_plus_128[i]); | |
| json_array_add_int_element (ar_coeffs_cr_plus_128, | |
| frame_header->film_grain_params.ar_coeffs_cr_plus_128[i]); | |
| } | |
| json_object_set_array_member (film_grain_params, "ar coeffs y plus 128", | |
| ar_coeffs_y_plus_128); | |
| json_object_set_array_member (film_grain_params, "ar coeffs cb plus 128", | |
| ar_coeffs_cb_plus_128); | |
| json_object_set_array_member (film_grain_params, "ar coeffs cr plus 128", | |
| ar_coeffs_cr_plus_128); | |
| json_object_set_int_member (film_grain_params, "ar coeff shift minus 6", | |
| frame_header->film_grain_params.ar_coeff_shift_minus_6); | |
| json_object_set_int_member (film_grain_params, "grain scale shift", | |
| frame_header->film_grain_params.grain_scale_shift); | |
| json_object_set_int_member (film_grain_params, "cb mult", | |
| frame_header->film_grain_params.cb_mult); | |
| json_object_set_int_member (film_grain_params, "cb luma mult", | |
| frame_header->film_grain_params.cb_luma_mult); | |
| json_object_set_int_member (film_grain_params, "cb offset", | |
| frame_header->film_grain_params.cb_offset); | |
| json_object_set_int_member (film_grain_params, "cr mult", | |
| frame_header->film_grain_params.cr_mult); | |
| json_object_set_int_member (film_grain_params, "cr luma mult", | |
| frame_header->film_grain_params.cr_luma_mult); | |
| json_object_set_int_member (film_grain_params, "cr offset", | |
| frame_header->film_grain_params.cr_offset); | |
| json_object_set_boolean_member (film_grain_params, "overlap flag", | |
| frame_header->film_grain_params.overlap_flag); | |
| json_object_set_boolean_member (film_grain_params, "clip to restricted range", | |
| frame_header->film_grain_params.clip_to_restricted_range); | |
| json_object_set_object_member (hdr, "film grain params", film_grain_params); | |
| json_object_set_int_member (hdr, "superres denom", | |
| frame_header->superres_denom); | |
| json_object_set_int_member (hdr, "frame is intra", | |
| frame_header->frame_is_intra); | |
| order_hints = json_array_new (); | |
| ref_frame_sign_bias = json_array_new (); | |
| for (i = 0; i < GST_AV1_NUM_REF_FRAMES; i++) { | |
| json_array_add_int_element (order_hints, frame_header->order_hints[i]); | |
| json_array_add_int_element (ref_frame_sign_bias, | |
| frame_header->ref_frame_sign_bias[i]); | |
| } | |
| json_object_set_array_member (hdr, "order hints", order_hints); | |
| json_object_set_array_member (hdr, "ref frame sign bias", | |
| ref_frame_sign_bias); | |
| json_object_set_int_member (hdr, "coded lossless", | |
| frame_header->coded_lossless); | |
| json_object_set_int_member (hdr, "all lossless", frame_header->all_lossless); | |
| lossless_array = json_array_new (); | |
| for (i = 0; i < GST_AV1_MAX_SEGMENTS; i++) | |
| json_array_add_int_element (lossless_array, | |
| frame_header->lossless_array[i]); | |
| json_object_set_array_member (hdr, "lossless array", lossless_array); | |
| seg_qm_level = json_array_new (); | |
| for (i = 0; i < 3; i++) | |
| for (j = 0; j < GST_AV1_MAX_SEGMENTS; j++) | |
| json_array_add_int_element (seg_qm_level, | |
| frame_header->seg_qm_Level[i][j]); | |
| json_object_set_array_member (hdr, "seg qm level", seg_qm_level); | |
| json_object_set_int_member (hdr, "upscaled width", | |
| frame_header->upscaled_width); | |
| json_object_set_int_member (hdr, "frame width", frame_header->frame_width); | |
| json_object_set_int_member (hdr, "frame height", frame_header->frame_height); | |
| json_object_set_int_member (hdr, "render width", frame_header->render_width); | |
| json_object_set_int_member (hdr, "render height", | |
| frame_header->render_height); | |
| json_object_set_int_member (hdr, "tx mode", frame_header->tx_mode); | |
| skip_mode_frame = json_array_new (); | |
| json_array_add_int_element (skip_mode_frame, | |
| frame_header->skip_mode_frame[0]); | |
| json_array_add_int_element (skip_mode_frame, | |
| frame_header->skip_mode_frame[1]); | |
| json_object_set_array_member (hdr, "skip mode frame", skip_mode_frame); | |
| json_object_set_object_member (json, "frame header", hdr); | |
| } | |
| static GstAV1ParserResult | |
| gst_av1_2_json_handle_one_obu (GstAV12json * self, GstAV1OBU * obu) | |
| { | |
| GstAV1ParserResult pres = GST_AV1_PARSER_OK; | |
| GstAV1FrameHeaderOBU frame_header; | |
| GstAV1FrameOBU frame; | |
| switch (obu->obu_type) { | |
| case GST_AV1_OBU_TEMPORAL_DELIMITER: | |
| pres = gst_av1_parser_parse_temporal_delimiter_obu (self->parser, obu); | |
| break; | |
| case GST_AV1_OBU_SEQUENCE_HEADER: | |
| { | |
| GstAV1SequenceHeaderOBU seq_header; | |
| pres = gst_av1_parser_parse_sequence_header_obu (self->parser, | |
| obu, &seq_header); | |
| if (pres == GST_AV1_PARSER_OK) | |
| gst_av1_2_json_sequence_header (self, &seq_header); | |
| break; | |
| } | |
| case GST_AV1_OBU_REDUNDANT_FRAME_HEADER: | |
| case GST_AV1_OBU_FRAME_HEADER: | |
| pres = gst_av1_parser_parse_frame_header_obu (self->parser, obu, | |
| &frame_header); | |
| if (pres == GST_AV1_PARSER_OK) | |
| gst_av1_2_json_frame_header (self, &frame_header); | |
| break; | |
| case GST_AV1_OBU_FRAME: | |
| pres = gst_av1_parser_parse_frame_obu (self->parser, obu, &frame); | |
| if (pres == GST_AV1_PARSER_OK) | |
| gst_av1_2_json_frame_header (self, &frame.frame_header); | |
| break; | |
| case GST_AV1_OBU_METADATA: | |
| { | |
| GstAV1MetadataOBU metadata; | |
| pres = gst_av1_parser_parse_metadata_obu (self->parser, obu, &metadata); | |
| break; | |
| } | |
| case GST_AV1_OBU_TILE_GROUP: | |
| { | |
| GstAV1TileGroupOBU tile_group; | |
| pres = | |
| gst_av1_parser_parse_tile_group_obu (self->parser, obu, &tile_group); | |
| break; | |
| } | |
| case GST_AV1_OBU_TILE_LIST: | |
| { | |
| GstAV1TileListOBU tile_list; | |
| pres = gst_av1_parser_parse_tile_list_obu (self->parser, obu, &tile_list); | |
| break; | |
| } | |
| case GST_AV1_OBU_PADDING: | |
| break; | |
| default: | |
| GST_WARNING_OBJECT (self, "an unrecognized obu type %d", obu->obu_type); | |
| pres = GST_AV1_PARSER_BITSTREAM_ERROR; | |
| break; | |
| } | |
| if (obu->obu_type == GST_AV1_OBU_FRAME_HEADER | |
| || obu->obu_type == GST_AV1_OBU_FRAME | |
| || obu->obu_type == GST_AV1_OBU_REDUNDANT_FRAME_HEADER) { | |
| GstAV1FrameHeaderOBU *fh = &frame_header; | |
| if (obu->obu_type == GST_AV1_OBU_FRAME) | |
| fh = &frame.frame_header; | |
| if (!fh->show_existing_frame || fh->frame_type == GST_AV1_KEY_FRAME) | |
| pres = gst_av1_parser_reference_frame_update (self->parser, fh); | |
| } | |
| return pres; | |
| } | |
| static GstFlowReturn | |
| gst_av1_2_json_chain (GstPad * sinkpad, GstObject * object, GstBuffer * in_buf) | |
| { | |
| GstAV12json *self = GST_AV1_2_JSON (object); | |
| JsonObject *json = self->json; | |
| GstAV1ParserResult pres; | |
| GstAV1OBU obu; | |
| GstBuffer *out_buf; | |
| gchar *json_string; | |
| guint32 offset = 0, consumed; | |
| guint length; | |
| GstMapInfo in_map, out_map; | |
| GstFlowReturn ret = GST_FLOW_OK; | |
| if (!gst_buffer_map (in_buf, &in_map, GST_MAP_READ)) { | |
| GST_ERROR_OBJECT (self, "Cannot map buffer"); | |
| return GST_FLOW_ERROR; | |
| } | |
| while (offset < in_map.size) { | |
| pres = | |
| gst_av1_parser_identify_one_obu (self->parser, in_map.data + offset, | |
| in_map.size - offset, &obu, &consumed); | |
| if (pres != GST_AV1_PARSER_OK) { | |
| GST_WARNING_OBJECT (self, "Cannot get OBU"); | |
| ret = GST_FLOW_ERROR; | |
| goto unmap; | |
| } | |
| pres = gst_av1_2_json_handle_one_obu (self, &obu); | |
| if (pres != GST_AV1_PARSER_OK) { | |
| GST_WARNING_OBJECT (self, "Cannot parse frame header"); | |
| ret = GST_FLOW_ERROR; | |
| goto unmap; | |
| } | |
| offset += consumed; | |
| } | |
| json_string = get_string_from_json_object (json); | |
| length = strlen (json_string); | |
| out_buf = gst_buffer_new_allocate (NULL, length, NULL); | |
| gst_buffer_map (out_buf, &out_map, GST_MAP_WRITE); | |
| if (length) | |
| memcpy (&out_map.data[0], json_string, length); | |
| gst_buffer_unmap (out_buf, &out_map); | |
| g_free (json_string); | |
| gst_buffer_copy_into (out_buf, in_buf, | |
| GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS | | |
| GST_BUFFER_COPY_METADATA, 0, -1); | |
| ret = gst_pad_push (self->srcpad, out_buf); | |
| unmap: | |
| switch (pres) { | |
| case GST_AV1_PARSER_BITSTREAM_ERROR: | |
| case GST_AV1_PARSER_MISSING_OBU_REFERENCE: | |
| case GST_AV1_PARSER_NO_MORE_DATA: | |
| if (self->use_annex_b) | |
| gst_av1_parser_reset_annex_b (self->parser); | |
| break; | |
| default: | |
| break; | |
| } | |
| gst_buffer_unmap (in_buf, &in_map); | |
| gst_buffer_unref (in_buf); | |
| return ret; | |
| } | |
| static void | |
| gst_av1_2_json_use_annexb (GstAV12json * self, GstCaps * caps) | |
| { | |
| if (caps && gst_caps_get_size (caps) > 0) { | |
| GstStructure *s = gst_caps_get_structure (caps, 0); | |
| const gchar *str_align = NULL; | |
| const gchar *str_stream = NULL; | |
| str_align = gst_structure_get_string (s, "alignment"); | |
| str_stream = gst_structure_get_string (s, "stream-format"); | |
| self->use_annex_b = FALSE; | |
| if (str_stream && g_strcmp0 (str_stream, "annexb") == 0) | |
| if (str_align && g_strcmp0 (str_align, "tu") == 0) { | |
| self->use_annex_b = TRUE; | |
| return; | |
| } | |
| } | |
| gst_av1_parser_reset (self->parser, self->use_annex_b); | |
| } | |
| static gboolean | |
| gst_av1_2_json_set_caps (GstAV12json * self, GstCaps * caps) | |
| { | |
| GstCaps *src_caps = | |
| gst_caps_new_simple ("text/x-json", "format", G_TYPE_STRING, "av1", NULL); | |
| GstEvent *event; | |
| event = gst_event_new_caps (src_caps); | |
| gst_caps_unref (src_caps); | |
| gst_av1_2_json_use_annexb (self, caps); | |
| return gst_pad_push_event (self->srcpad, event); | |
| } | |
| static gboolean | |
| gst_av1_2_json_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) | |
| { | |
| GstAV12json *self = GST_AV1_2_JSON (parent); | |
| gboolean res = TRUE; | |
| switch (GST_EVENT_TYPE (event)) { | |
| case GST_EVENT_CAPS: | |
| { | |
| GstCaps *caps; | |
| gst_event_parse_caps (event, &caps); | |
| res = gst_av1_2_json_set_caps (self, caps); | |
| gst_event_unref (event); | |
| break; | |
| } | |
| default: | |
| res = gst_pad_event_default (pad, parent, event); | |
| break; | |
| } | |
| return res; | |
| } | |
| static void | |
| gst_av1_2_json_class_init (GstAV12jsonClass * klass) | |
| { | |
| GObjectClass *gobject_class; | |
| GstElementClass *gstelement_class; | |
| gobject_class = (GObjectClass *) klass; | |
| gstelement_class = (GstElementClass *) klass; | |
| gobject_class->finalize = gst_av1_2_json_finalize; | |
| gst_element_class_add_static_pad_template (gstelement_class, &src_factory); | |
| gst_element_class_add_static_pad_template (gstelement_class, &sink_factory); | |
| gst_element_class_set_static_metadata (gstelement_class, "Av12json", | |
| "Transform", | |
| "AV1 to json element", | |
| "Benjamin Gaignard <benjamin.gaignard@collabora.com>"); | |
| } | |
| static void | |
| gst_av1_2_json_init (GstAV12json * self) | |
| { | |
| self->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink"); | |
| gst_pad_set_chain_function (self->sinkpad, gst_av1_2_json_chain); | |
| gst_element_add_pad (GST_ELEMENT (self), self->sinkpad); | |
| gst_pad_set_event_function (self->sinkpad, | |
| GST_DEBUG_FUNCPTR (gst_av1_2_json_sink_event)); | |
| self->srcpad = gst_pad_new_from_static_template (&src_factory, "src"); | |
| gst_element_add_pad (GST_ELEMENT (self), self->srcpad); | |
| self->json = json_object_new (); | |
| self->parser = gst_av1_parser_new (); | |
| gst_av1_parser_reset (self->parser, FALSE); | |
| } |