• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // Tests PPB_MediaStreamVideoTrack interface.
6 
7 #include "ppapi/tests/test_media_stream_video_track.h"
8 
9 #include "ppapi/c/private/ppb_testing_private.h"
10 #include "ppapi/cpp/completion_callback.h"
11 #include "ppapi/cpp/instance.h"
12 #include "ppapi/cpp/var.h"
13 #include "ppapi/cpp/video_frame.h"
14 #include "ppapi/tests/test_utils.h"
15 #include "ppapi/tests/testing_instance.h"
16 
17 REGISTER_TEST_CASE(MediaStreamVideoTrack);
18 
19 namespace {
20 
21 const int32_t kTimes = 3;
22 const int32_t kDefaultWidth = 640;
23 const int32_t kDefaultHeight = 480;
24 const char kJSCode[] =
25     "function gotStream(stream) {"
26     "  var track = stream.getVideoTracks()[0];"
27     "  var plugin = document.getElementById('plugin');"
28     "  plugin.postMessage(track);"
29     "}"
30     "var constraints = {"
31     "  audio: false,"
32     "  video: { mandatory: { minWidth: 640, minHeight: 480 } }"
33     "};"
34     "navigator.getUserMedia ="
35     "    navigator.getUserMedia || navigator.webkitGetUserMedia;"
36     "navigator.getUserMedia(constraints,"
37     "    gotStream, function() {});";
38 }
39 
TestMediaStreamVideoTrack(TestingInstance * instance)40 TestMediaStreamVideoTrack::TestMediaStreamVideoTrack(TestingInstance* instance)
41     : TestCase(instance),
42       event_(instance_->pp_instance()) {
43 }
44 
Init()45 bool TestMediaStreamVideoTrack::Init() {
46   return true;
47 }
48 
~TestMediaStreamVideoTrack()49 TestMediaStreamVideoTrack::~TestMediaStreamVideoTrack() {
50 }
51 
RunTests(const std::string & filter)52 void TestMediaStreamVideoTrack::RunTests(const std::string& filter) {
53   RUN_TEST(Create, filter);
54   RUN_TEST(GetFrame, filter);
55   RUN_TEST(Configure, filter);
56 }
57 
HandleMessage(const pp::Var & message)58 void TestMediaStreamVideoTrack::HandleMessage(const pp::Var& message) {
59   if (message.is_resource())
60     video_track_ = pp::MediaStreamVideoTrack(message.AsResource());
61   event_.Signal();
62 }
63 
TestCreate()64 std::string TestMediaStreamVideoTrack::TestCreate() {
65   // Create a track.
66   instance_->EvalScript(kJSCode);
67   event_.Wait();
68   event_.Reset();
69 
70   ASSERT_FALSE(video_track_.is_null());
71   ASSERT_FALSE(video_track_.HasEnded());
72   ASSERT_FALSE(video_track_.GetId().empty());
73 
74   // Close the track.
75   video_track_.Close();
76   ASSERT_TRUE(video_track_.HasEnded());
77   video_track_ = pp::MediaStreamVideoTrack();
78   PASS();
79 }
80 
TestGetFrame()81 std::string TestMediaStreamVideoTrack::TestGetFrame() {
82   // Create a track.
83   instance_->EvalScript(kJSCode);
84   event_.Wait();
85   event_.Reset();
86 
87   ASSERT_FALSE(video_track_.is_null());
88   ASSERT_FALSE(video_track_.HasEnded());
89   ASSERT_FALSE(video_track_.GetId().empty());
90 
91   PP_TimeDelta timestamp = 0.0;
92 
93   // Get |kTimes| frames.
94   for (int i = 0; i < kTimes; ++i) {
95     TestCompletionCallbackWithOutput<pp::VideoFrame> cc(
96         instance_->pp_instance(), false);
97     cc.WaitForResult(video_track_.GetFrame(cc.GetCallback()));
98     ASSERT_EQ(PP_OK, cc.result());
99     pp::VideoFrame frame = cc.output();
100     ASSERT_FALSE(frame.is_null());
101     ASSERT_TRUE(frame.GetFormat() == PP_VIDEOFRAME_FORMAT_YV12 ||
102                 frame.GetFormat() == PP_VIDEOFRAME_FORMAT_I420);
103 
104     pp::Size size;
105     ASSERT_TRUE(frame.GetSize(&size));
106     ASSERT_EQ(size.width(), kDefaultWidth);
107     ASSERT_EQ(size.height(), kDefaultHeight);
108 
109     ASSERT_GE(frame.GetTimestamp(), timestamp);
110     timestamp = frame.GetTimestamp();
111 
112     ASSERT_GT(frame.GetDataBufferSize(), 0U);
113     ASSERT_TRUE(frame.GetDataBuffer() != NULL);
114 
115     video_track_.RecycleFrame(frame);
116 
117     // A recycled frame should be invalidated.
118     ASSERT_EQ(frame.GetFormat(), PP_VIDEOFRAME_FORMAT_UNKNOWN);
119     ASSERT_FALSE(frame.GetSize(&size));
120     ASSERT_EQ(frame.GetDataBufferSize(), 0U);
121     ASSERT_TRUE(frame.GetDataBuffer() == NULL);
122   }
123 
124   // Close the track.
125   video_track_.Close();
126   ASSERT_TRUE(video_track_.HasEnded());
127   video_track_ = pp::MediaStreamVideoTrack();
128   PASS();
129 }
130 
TestConfigure()131 std::string TestMediaStreamVideoTrack::TestConfigure() {
132   // Create a track.
133   instance_->EvalScript(kJSCode);
134   event_.Wait();
135   event_.Reset();
136 
137   ASSERT_FALSE(video_track_.is_null());
138   ASSERT_FALSE(video_track_.HasEnded());
139   ASSERT_FALSE(video_track_.GetId().empty());
140 
141   // Configure format.
142   struct {
143     int32_t format;
144     int32_t expected_format;
145   } formats[] = {
146     { PP_VIDEOFRAME_FORMAT_BGRA, PP_VIDEOFRAME_FORMAT_BGRA }, // To RGBA.
147     { PP_VIDEOFRAME_FORMAT_I420, PP_VIDEOFRAME_FORMAT_I420 }, // To I420.
148     { PP_VIDEOFRAME_FORMAT_YV12, PP_VIDEOFRAME_FORMAT_YV12 }, // To YV12.
149     { PP_VIDEOFRAME_FORMAT_BGRA, PP_VIDEOFRAME_FORMAT_BGRA }, // To RGBA.
150     { PP_VIDEOFRAME_FORMAT_UNKNOWN, PP_VIDEOFRAME_FORMAT_YV12 }, // To default.
151   };
152   for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); ++i) {
153     TestCompletionCallback cc1(instance_->pp_instance(), false);
154     int32_t attrib_list[] = {
155       PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT, formats[i].format,
156       PP_MEDIASTREAMVIDEOTRACK_ATTRIB_NONE,
157     };
158     cc1.WaitForResult(video_track_.Configure(attrib_list, cc1.GetCallback()));
159     ASSERT_EQ(PP_OK, cc1.result());
160 
161     for (int j = 0; j < kTimes; ++j) {
162       TestCompletionCallbackWithOutput<pp::VideoFrame> cc2(
163           instance_->pp_instance(), false);
164       cc2.WaitForResult(video_track_.GetFrame(cc2.GetCallback()));
165       ASSERT_EQ(PP_OK, cc2.result());
166       pp::VideoFrame frame = cc2.output();
167       ASSERT_FALSE(frame.is_null());
168       if (formats[i].format != PP_VIDEOFRAME_FORMAT_UNKNOWN) {
169         ASSERT_EQ(frame.GetFormat(), formats[i].expected_format);
170       } else {
171         // Both YV12 and I420 are acceptable as default YUV formats.
172         ASSERT_TRUE(frame.GetFormat() == PP_VIDEOFRAME_FORMAT_YV12 ||
173                     frame.GetFormat() == PP_VIDEOFRAME_FORMAT_I420);
174       }
175 
176       pp::Size size;
177       ASSERT_TRUE(frame.GetSize(&size));
178       ASSERT_EQ(size.width(), kDefaultWidth);
179       ASSERT_EQ(size.height(), kDefaultHeight);
180 
181       ASSERT_GT(frame.GetDataBufferSize(), 0U);
182       ASSERT_TRUE(frame.GetDataBuffer() != NULL);
183 
184       video_track_.RecycleFrame(frame);
185     }
186   }
187 
188   // Configure size.
189   struct {
190     int32_t width;
191     int32_t height;
192     int32_t expect_width;
193     int32_t expect_height;
194   } sizes[] = {
195     { 72, 72, 72, 72 }, // To 72x27.
196     { 1024, 768, 1024, 768 }, // To 1024x768.
197     { 0, 0, kDefaultWidth, kDefaultHeight }, // To default.
198   };
199   for (size_t i = 0; i < sizeof(sizes) / sizeof(sizes[0]); ++i) {
200     TestCompletionCallback cc1(instance_->pp_instance(), false);
201     int32_t attrib_list[] = {
202       PP_MEDIASTREAMVIDEOTRACK_ATTRIB_WIDTH, sizes[i].width,
203       PP_MEDIASTREAMVIDEOTRACK_ATTRIB_HEIGHT, sizes[i].height,
204       PP_MEDIASTREAMVIDEOTRACK_ATTRIB_NONE,
205     };
206     cc1.WaitForResult(video_track_.Configure(attrib_list, cc1.GetCallback()));
207     ASSERT_EQ(PP_OK, cc1.result());
208 
209     for (int j = 0; j < kTimes; ++j) {
210       TestCompletionCallbackWithOutput<pp::VideoFrame> cc2(
211           instance_->pp_instance(), false);
212       cc2.WaitForResult(video_track_.GetFrame(cc2.GetCallback()));
213       ASSERT_EQ(PP_OK, cc2.result());
214       pp::VideoFrame frame = cc2.output();
215       ASSERT_FALSE(frame.is_null());
216       ASSERT_TRUE(frame.GetFormat() == PP_VIDEOFRAME_FORMAT_YV12 ||
217                   frame.GetFormat() == PP_VIDEOFRAME_FORMAT_I420);
218 
219       pp::Size size;
220       ASSERT_TRUE(frame.GetSize(&size));
221       ASSERT_EQ(size.width(), sizes[i].expect_width);
222       ASSERT_EQ(size.height(), sizes[i].expect_height);
223 
224       ASSERT_GT(frame.GetDataBufferSize(), 0U);
225       ASSERT_TRUE(frame.GetDataBuffer() != NULL);
226 
227       video_track_.RecycleFrame(frame);
228     }
229   }
230 
231   // Close the track.
232   video_track_.Close();
233   ASSERT_TRUE(video_track_.HasEnded());
234   video_track_ = pp::MediaStreamVideoTrack();
235   PASS();
236 }
237