• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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