Home | History | Annotate | Download | only in tests
      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 
     40 TestMediaStreamVideoTrack::TestMediaStreamVideoTrack(TestingInstance* instance)
     41     : TestCase(instance),
     42       event_(instance_->pp_instance()) {
     43 }
     44 
     45 bool TestMediaStreamVideoTrack::Init() {
     46   return true;
     47 }
     48 
     49 TestMediaStreamVideoTrack::~TestMediaStreamVideoTrack() {
     50 }
     51 
     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 
     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 
     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 
     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 
    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