1 /* GStreamer
2 * Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <gst/check/gstcheck.h>
25 #include <gst/check/gstharness.h>
26 #include "vp9parse.h"
27 #include <string.h>
28
29 typedef struct
30 {
31 const guint8 *data;
32 guint len;
33 gboolean superframe;
34 guint subframe_len[2];
35 } GstVp9ParseTestFrameData;
36
37 static void
run_split_superframe_with_caps(const gchar * in_caps)38 run_split_superframe_with_caps (const gchar * in_caps)
39 {
40 GstHarness *h;
41 GstBuffer *in_buf, *out_buf = NULL;
42 GstMapInfo map;
43 GstFlowReturn ret;
44 gint i = 0;
45 GstVp9ParseTestFrameData frames[] = {
46 {profile_0_frame0, profile_0_frame0_len, FALSE, {profile_0_frame0_len, 0}},
47 {profile_0_frame1, profile_0_frame1_len, TRUE, {profile_0_frame1_first_len,
48 profile_0_frame1_last_len}},
49 {profile_0_frame2, profile_0_frame2_len, FALSE, {profile_0_frame2_len, 0}},
50 };
51
52 h = gst_harness_new_parse ("vp9parse");
53 fail_unless (h != NULL);
54
55 gst_harness_set_sink_caps_str (h, "video/x-vp9,alignment=(string)frame");
56
57 /* default alignment is super-frame */
58 gst_harness_set_src_caps_str (h, in_caps);
59
60 gst_harness_play (h);
61 for (i = 0; i < G_N_ELEMENTS (frames); i++) {
62 in_buf = gst_buffer_new_and_alloc (frames[i].len);
63 gst_buffer_map (in_buf, &map, GST_MAP_WRITE);
64 memcpy (map.data, frames[i].data, frames[i].len);
65 gst_buffer_unmap (in_buf, &map);
66
67 ret = gst_harness_push (h, in_buf);
68 fail_unless (ret == GST_FLOW_OK, "GstFlowReturn was %s",
69 gst_flow_get_name (ret));
70 out_buf = gst_harness_try_pull (h);
71 fail_unless (out_buf);
72 fail_unless_equals_int (gst_buffer_get_size (out_buf),
73 frames[i].subframe_len[0]);
74
75 if (i == 0) {
76 GstEvent *event;
77 GstCaps *caps = NULL;
78 GstStructure *s;
79 const gchar *profile;
80 gint width, height;
81
82 fail_if (GST_BUFFER_FLAG_IS_SET (out_buf, GST_BUFFER_FLAG_DELTA_UNIT));
83
84 while ((event = gst_harness_try_pull_event (h))) {
85 GstCaps *event_caps;
86 if (GST_EVENT_TYPE (event) != GST_EVENT_CAPS) {
87 gst_event_unref (event);
88 continue;
89 }
90
91 gst_event_parse_caps (event, &event_caps);
92 gst_caps_replace (&caps, event_caps);
93 gst_event_unref (event);
94 }
95
96 fail_unless (caps != NULL);
97 s = gst_caps_get_structure (caps, 0);
98 fail_unless (gst_structure_get_int (s, "width", &width));
99 fail_unless (gst_structure_get_int (s, "height", &height));
100 fail_unless ((profile = gst_structure_get_string (s, "profile")));
101
102 fail_unless_equals_int (width, 256);
103 fail_unless_equals_int (height, 144);
104 fail_unless_equals_string (profile, "0");
105 gst_caps_unref (caps);
106 } else {
107 fail_unless (GST_BUFFER_FLAG_IS_SET (out_buf,
108 GST_BUFFER_FLAG_DELTA_UNIT));
109 }
110
111 if (frames[i].superframe) {
112 /* this is decoding only frame */
113 fail_unless (GST_BUFFER_FLAG_IS_SET (out_buf,
114 GST_BUFFER_FLAG_DECODE_ONLY));
115 fail_unless (GST_BUFFER_FLAG_IS_SET (out_buf,
116 GST_BUFFER_FLAG_DELTA_UNIT));
117 gst_clear_buffer (&out_buf);
118
119 out_buf = gst_harness_try_pull (h);
120 fail_unless (out_buf);
121 fail_unless_equals_int (gst_buffer_get_size (out_buf),
122 frames[i].subframe_len[1]);
123 fail_unless (GST_BUFFER_FLAG_IS_SET (out_buf,
124 GST_BUFFER_FLAG_DELTA_UNIT));
125 }
126
127 gst_clear_buffer (&out_buf);
128 }
129
130 gst_harness_teardown (h);
131 }
132
GST_START_TEST(test_split_superframe)133 GST_START_TEST (test_split_superframe)
134 {
135 /* vp9parse will split frame if downstream alignment is frame
136 * whatever the upstream alignment was specified */
137 run_split_superframe_with_caps ("video/x-vp9");
138 run_split_superframe_with_caps ("video/x-vp9,alignment=(string)super-frame");
139 run_split_superframe_with_caps ("video/x-vp9,alignment=(string)frame");
140 }
141
142 GST_END_TEST;
143
144 static Suite *
vp9parse_suite(void)145 vp9parse_suite (void)
146 {
147 Suite *s;
148 TCase *tc_chain;
149
150 s = suite_create ("vp9parse");
151 tc_chain = tcase_create ("general");
152
153 suite_add_tcase (s, tc_chain);
154
155 tcase_add_test (tc_chain, test_split_superframe);
156
157 return s;
158 }
159
160 GST_CHECK_MAIN (vp9parse);
161