Changeset 171033 in webkit
- Timestamp:
- Jul 12, 2014, 3:39:43 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r171014 r171033 1 2014-07-11 Jer Noble <jer.noble@apple.com> 2 3 [MSE] http/tests/media/media-source/mediasource-duration.html is failing. 4 https://bugs.webkit.org/show_bug.cgi?id=134852 5 6 Reviewed by Eric Carlson. 7 8 Eliminate flakiness in the mediasource-duration.html test by not playing 9 the media while testing seeking and duration. 10 * http/tests/media/media-source/mediasource-duration.html: 11 12 Update testharness.js to the latest W3C version: 13 * http/tests/w3c/resources/testharness.js: 14 1 15 2014-07-11 Zalan Bujtas <zalan@apple.com> 2 16 -
trunk/LayoutTests/http/tests/media/media-source/mediasource-duration.html
r170542 r171033 19 19 var truncatedDuration = seekTo / 2.0; 20 20 21 mediaElement.play();22 23 21 // Append all the segments 24 22 test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer'); 25 test.expectEvent(mediaElement, 'playing', 'Playing triggered');26 23 sourceBuffer.appendBuffer(mediaData); 27 24 … … 127 124 test.waitForExpectedEvents(function() 128 125 { 129 assert_ equals(mediaElement.currentTime, truncatedDuration,126 assert_approx_equals(mediaElement.currentTime, truncatedDuration, 0.05, 130 127 'Playback time has reached truncatedDuration'); 131 assert_ equals(mediaElement.duration, truncatedDuration,128 assert_approx_equals(mediaElement.duration, truncatedDuration, 0.05, 132 129 'mediaElement truncatedDuration after seek to it'); 133 assert_ equals(mediaSource.duration, truncatedDuration,130 assert_approx_equals(mediaSource.duration, truncatedDuration, 0.05, 134 131 'mediaSource truncatedDuration after seek to it'); 135 132 assert_false(mediaElement.seeking, 'mediaElement.seeking after seeked to truncatedDuration'); … … 155 152 }); 156 153 157 mediaElement.play();158 159 154 // Append all the segments 160 155 test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer'); 161 test.expectEvent(mediaElement, 'playing', 'Playing triggered');162 156 sourceBuffer.appendBuffer(mediaData); 163 157 … … 202 196 } 203 197 198 mediaElement.play(); 199 204 200 // Allow media to play to end while counting 'durationchange' events. 201 test.expectEvent(mediaElement, 'playing', 'Playing triggered'); 205 202 test.expectEvent(mediaElement, 'ended', 'Playback ended'); 206 203 test.waitForExpectedEvents(function() … … 212 209 }); 213 210 }, 'Test setting same duration multiple times does not fire duplicate durationchange', {timeout: 2500}); 211 214 212 </script> 215 213 </body> -
trunk/LayoutTests/http/tests/w3c/resources/testharness.js
r151122 r171033 60 60 * 61 61 * Additionally, test-specific metadata can be passed in the properties. These 62 * are used when the individual test has different metadata from that stored 62 * are used when the individual test has different metadata from that stored 63 63 * in the <head>. 64 64 * The recognized metadata properties are: 65 65 * 66 * help - The url of the part of the specification being tested 67 * 68 * assert - A human readable description of what the test is attempting 66 * help - The url or an array of urls of the part(s) of the specification(s) 67 * being tested 68 * 69 * assert - A human readable description of what the test is attempting 69 70 * to prove 70 71 * 71 72 * author - Name and contact information for the author of the test in the 72 73 * format: "Name <email_addr>" or "Name http://contact/url" 73 *74 * flags - space separated list of test flags in addition to any present in75 * the head metadata76 74 * 77 75 * == Asynchronous Tests == … … 137 135 * and may cause a file to stop testing. 138 136 * 137 * == Cleanup == 138 * 139 * Occasionally tests may create state that will persist beyond the test itself. 140 * In order to ensure that tests are independent, such state should be cleaned 141 * up once the test has a result. This can be achieved by adding cleanup 142 * callbacks to the test. Such callbacks are registered using the add_cleanup 143 * function on the test object. All registered callbacks will be run as soon as 144 * the test result is known. For example 145 * test(function() { 146 * window.some_global = "example"; 147 * this.add_cleanup(function() {delete window.some_global}); 148 * assert_true(false); 149 * }); 150 * 151 * == Harness Timeout == 152 * 153 * The overall harness admits two timeout values "normal" (the 154 * default) and "long", used for tests which have an unusually long 155 * runtime. After the timeout is reached, the harness will stop 156 * waiting for further async tests to complete. By default the 157 * timeouts are set to 10s and 60s, respectively, but may be changed 158 * when the test is run on hardware with different performance 159 * characteristics to a common desktop computer. In order to opt-in 160 * to the longer test timeout, the test must specify a meta element: 161 * <meta name="timeout" content="long"> 162 * 139 163 * == Setup == 140 164 * … … 150 174 * harness. Currently recognised properties are: 151 175 * 152 * timeout - The time in ms after which the harness should stop waiting for153 * tests to complete (this is different to the per-test timeout154 * because async tests do not start their timer until .step is called)155 176 * 156 177 * explicit_done - Wait for an explicit call to done() before declaring all … … 167 188 * that has its own timeout mechanism). 168 189 * 190 * allow_uncaught_exception - don't treat an uncaught exception as an error; 191 * needed when e.g. testing the window.onerror 192 * handler. 193 * 194 * timeout_multiplier - Multiplier to apply to per-test timeouts. 195 * 169 196 * == Determining when all tests are complete == 170 197 * … … 205 232 * the test. 206 233 * 207 * The properties argument is identical to that for test(). This may be a 234 * The properties argument is identical to that for test(). This may be a 208 235 * single object (used for all generated tests) or an array. 209 236 * … … 290 317 * assert_approx_equals(actual, expected, epsilon, description) 291 318 * asserts that /actual/ is a number within +/- /epsilon/ of /expected/ 319 * 320 * assert_less_than(actual, expected, description) 321 * asserts that /actual/ is a number less than /expected/ 322 * 323 * assert_greater_than(actual, expected, description) 324 * asserts that /actual/ is a number greater than /expected/ 325 * 326 * assert_less_than_equal(actual, expected, description) 327 * asserts that /actual/ is a number less than or equal to /expected/ 328 * 329 * assert_greater_than_equal(actual, expected, description) 330 * asserts that /actual/ is a number greater than or equal to /expected/ 292 331 * 293 332 * assert_regexp_match(actual, expected, description) … … 332 371 * with signature assert_func(actual, expected, args_1, ..., args_N). Note that tests 333 372 * with multiple allowed pass conditions are bad practice unless the spec specifically 334 * allows multiple behaviours. Test authors should not use this method simply to hide 373 * allows multiple behaviours. Test authors should not use this method simply to hide 335 374 * UA bugs. 336 375 * … … 347 386 { 348 387 var debug = false; 349 // default timeout is 5seconds, test can override if needed388 // default timeout is 10 seconds, test can override if needed 350 389 var settings = { 351 output:true, 352 timeout:5000, 353 test_timeout:2000 390 output:true, 391 harness_timeout:{ 392 "normal":10000, 393 "long":60000 394 }, 395 test_timeout:null 354 396 }; 355 397 … … 363 405 { 364 406 var scripts = document.getElementsByTagName("script"); 365 for (var i = 0; i < scripts.length; i++) 366 { 367 if (scripts[i].src) 368 { 407 for (var i = 0; i < scripts.length; i++) { 408 if (scripts[i].src) { 369 409 var src = scripts[i].src; 370 } 371 else if (scripts[i].href) 372 { 410 } else if (scripts[i].href) { 373 411 //SVG case 374 412 var src = scripts[i].href.baseVal; 375 413 } 376 if (src && src.slice(src.length - "testharness.js".length) === "testharness.js") 377 {414 415 if (src && src.slice(src.length - "testharness.js".length) === "testharness.js") { 378 416 script_prefix = src.slice(0, src.length - "testharness.js".length); 379 417 break; … … 390 428 { 391 429 //Don't use document.title to work around an Opera bug in XHTML documents 392 var prefix = document.getElementsByTagName("title").length > 0 ? 393 document.getElementsByTagName("title")[0].firstChild.data : 394 "Untitled"; 430 var title = document.getElementsByTagName("title")[0]; 431 var prefix = (title && title.firstChild && title.firstChild.data) || "Untitled"; 395 432 var suffix = name_counter > 0 ? " " + name_counter : ""; 396 433 name_counter++; … … 403 440 properties = properties ? properties : {}; 404 441 var test_obj = new Test(test_name, properties); 405 test_obj.step(func );406 if (test_obj. status === test_obj.NOTRUN) {442 test_obj.step(func, test_obj, test_obj); 443 if (test_obj.phase === test_obj.phases.STARTED) { 407 444 test_obj.done(); 408 445 } … … 432 469 func = func_or_properties; 433 470 properties = maybe_properties; 434 } else if (func_or_properties instanceof Function) {471 } else if (func_or_properties instanceof Function) { 435 472 func = func_or_properties; 436 473 } else { … … 452 489 { 453 490 func.apply(this, x.slice(1)); 454 }, 455 name, 491 }, 492 name, 456 493 Array.isArray(properties) ? properties[i] : properties); 457 494 }); … … 460 497 function on_event(object, event, callback) 461 498 { 462 object.addEventListener(event, callback, false);499 object.addEventListener(event, callback, false); 463 500 } 464 501 … … 483 520 484 521 /* 522 * Return true if object is probably a Node object. 523 */ 524 function is_node(object) 525 { 526 // I use duck-typing instead of instanceof, because 527 // instanceof doesn't work if the node is from another window (like an 528 // iframe's contentWindow): 529 // http://www.w3.org/Bugs/Public/show_bug.cgi?id=12295 530 if ("nodeType" in object 531 && "nodeName" in object 532 && "nodeValue" in object 533 && "childNodes" in object) { 534 try { 535 object.nodeType; 536 } catch (e) { 537 // The object is probably Node.prototype or another prototype 538 // object that inherits from it, and not a Node instance. 539 return false; 540 } 541 return true; 542 } 543 return false; 544 } 545 546 /* 485 547 * Convert a value to a nice, human-readable string 486 548 */ 487 function format_value(val) 488 { 489 if (Array.isArray(val)) 490 { 491 return "[" + val.map(format_value).join(", ") + "]"; 492 } 493 494 switch (typeof val) 495 { 549 function format_value(val, seen) 550 { 551 if (!seen) { 552 seen = []; 553 } 554 if (typeof val === "object" && val !== null) { 555 if (seen.indexOf(val) >= 0) { 556 return "[...]"; 557 } 558 seen.push(val); 559 } 560 if (Array.isArray(val)) { 561 return "[" + val.map(function(x) {return format_value(x, seen)}).join(", ") + "]"; 562 } 563 564 switch (typeof val) { 496 565 case "string": 497 566 val = val.replace("\\", "\\\\"); 498 for (var i = 0; i < 32; i++) 499 { 567 for (var i = 0; i < 32; i++) { 500 568 var replace = "\\"; 501 569 switch (i) { … … 542 610 // In JavaScript, -0 === 0 and String(-0) == "0", so we have to 543 611 // special-case. 544 if (val === -0 && 1/val === -Infinity) 545 { 612 if (val === -0 && 1/val === -Infinity) { 546 613 return "-0"; 547 614 } 548 615 return String(val); 549 616 case "object": 550 if (val === null) 551 { 617 if (val === null) { 552 618 return "null"; 553 619 } 554 620 555 621 // Special-case Node objects, since those come up a lot in my tests. I 556 // ignore namespaces. I use duck-typing instead of instanceof, because 557 // instanceof doesn't work if the node is from another window (like an 558 // iframe's contentWindow): 559 // http://www.w3.org/Bugs/Public/show_bug.cgi?id=12295 560 if ("nodeType" in val 561 && "nodeName" in val 562 && "nodeValue" in val 563 && "childNodes" in val) 564 { 565 switch (val.nodeType) 566 { 622 // ignore namespaces. 623 if (is_node(val)) { 624 switch (val.nodeType) { 567 625 case Node.ELEMENT_NODE: 568 626 var ret = "<" + val.tagName.toLowerCase(); 569 for (var i = 0; i < val.attributes.length; i++) 570 { 627 for (var i = 0; i < val.attributes.length; i++) { 571 628 ret += " " + val.attributes[i].name + '="' + val.attributes[i].value + '"'; 572 629 } … … 616 673 617 674 function same_value(x, y) { 618 if (y !== y) 619 { 675 if (y !== y) { 620 676 //NaN case 621 677 return x !== x; 622 678 } 623 elseif (x === 0 && y === 0) {679 if (x === 0 && y === 0) { 624 680 //Distinguish +0 and -0 625 681 return 1/x === 1/y; 626 682 } 627 else 628 { 629 //typical case 630 return x === y; 631 } 683 return x === y; 632 684 } 633 685 … … 638 690 * are the same object 639 691 */ 640 if (typeof actual != typeof expected) 641 { 692 if (typeof actual != typeof expected) { 642 693 assert(false, "assert_equals", description, 643 694 "expected (" + typeof expected + ") ${expected} but got (" + typeof actual + ") ${actual}", … … 679 730 680 731 var p; 681 for (p in actual) 682 { 732 for (p in actual) { 683 733 assert(expected.hasOwnProperty(p), "assert_object_equals", description, 684 734 "unexpected property ${p}", {p:p}); 685 735 686 if (typeof actual[p] === "object" && actual[p] !== null) 687 { 688 if (stack.indexOf(actual[p]) === -1) 689 { 736 if (typeof actual[p] === "object" && actual[p] !== null) { 737 if (stack.indexOf(actual[p]) === -1) { 690 738 check_equal(actual[p], expected[p], stack); 691 739 } 692 } 693 else 694 { 740 } else { 695 741 assert(same_value(actual[p], expected[p]), "assert_object_equals", description, 696 742 "property ${p} expected ${expected} got ${actual}", … … 698 744 } 699 745 } 700 for (p in expected) 701 { 746 for (p in expected) { 702 747 assert(actual.hasOwnProperty(p), 703 748 "assert_object_equals", description, … … 717 762 {expected:expected.length, actual:actual.length}); 718 763 719 for (var i=0; i < actual.length; i++) 720 { 764 for (var i = 0; i < actual.length; i++) { 721 765 assert(actual.hasOwnProperty(i) === expected.hasOwnProperty(i), 722 766 "assert_array_equals", description, … … 749 793 expose(assert_approx_equals, "assert_approx_equals"); 750 794 795 function assert_less_than(actual, expected, description) 796 { 797 /* 798 * Test if a primitive number is less than another 799 */ 800 assert(typeof actual === "number", 801 "assert_less_than", description, 802 "expected a number but got a ${type_actual}", 803 {type_actual:typeof actual}); 804 805 assert(actual < expected, 806 "assert_less_than", description, 807 "expected a number less than ${expected} but got ${actual}", 808 {expected:expected, actual:actual}); 809 }; 810 expose(assert_less_than, "assert_less_than"); 811 812 function assert_greater_than(actual, expected, description) 813 { 814 /* 815 * Test if a primitive number is greater than another 816 */ 817 assert(typeof actual === "number", 818 "assert_greater_than", description, 819 "expected a number but got a ${type_actual}", 820 {type_actual:typeof actual}); 821 822 assert(actual > expected, 823 "assert_greater_than", description, 824 "expected a number greater than ${expected} but got ${actual}", 825 {expected:expected, actual:actual}); 826 }; 827 expose(assert_greater_than, "assert_greater_than"); 828 829 function assert_less_than_equal(actual, expected, description) 830 { 831 /* 832 * Test if a primitive number is less than or equal to another 833 */ 834 assert(typeof actual === "number", 835 "assert_less_than_equal", description, 836 "expected a number but got a ${type_actual}", 837 {type_actual:typeof actual}); 838 839 assert(actual <= expected, 840 "assert_less_than", description, 841 "expected a number less than or equal to ${expected} but got ${actual}", 842 {expected:expected, actual:actual}); 843 }; 844 expose(assert_less_than_equal, "assert_less_than_equal"); 845 846 function assert_greater_than_equal(actual, expected, description) 847 { 848 /* 849 * Test if a primitive number is greater than or equal to another 850 */ 851 assert(typeof actual === "number", 852 "assert_greater_than_equal", description, 853 "expected a number but got a ${type_actual}", 854 {type_actual:typeof actual}); 855 856 assert(actual >= expected, 857 "assert_greater_than_equal", description, 858 "expected a number greater than or equal to ${expected} but got ${actual}", 859 {expected:expected, actual:actual}); 860 }; 861 expose(assert_greater_than_equal, "assert_greater_than_equal"); 862 751 863 function assert_regexp_match(actual, expected, description) { 752 864 /* … … 822 934 "changing property ${p} succeeded", 823 935 {p:property_name}); 824 } 825 finally 826 { 936 } finally { 827 937 object[property_name] = initial_value; 828 938 } … … 832 942 function assert_throws(code, func, description) 833 943 { 834 try 835 { 944 try { 836 945 func.call(this); 837 946 assert(false, "assert_throws", description, 838 947 "${func} did not throw", {func:func}); 839 } 840 catch(e) 841 { 948 } catch (e) { 842 949 if (e instanceof AssertionError) { 843 throw(e); 844 } 845 if (code === null) 846 { 950 throw e; 951 } 952 if (code === null) { 847 953 return; 848 954 } 849 if (typeof code === "object") 850 { 955 if (typeof code === "object") { 851 956 assert(typeof e == "object" && "name" in e && e.name == code.name, 852 957 "assert_throws", description, … … 915 1020 }; 916 1021 917 if (!(name in name_code_map)) 918 { 1022 if (!(name in name_code_map)) { 919 1023 throw new AssertionError('Test bug: unrecognized DOMException code "' + code + '" passed to assert_throws()'); 920 1024 } … … 923 1027 924 1028 if (required_props.code === 0 925 || ("name" in e && e.name !== e.name.toUpperCase() && e.name !== "DOMException")) 926 { 1029 || ("name" in e && e.name !== e.name.toUpperCase() && e.name !== "DOMException")) { 927 1030 // New style exception: also test the name property. 928 1031 required_props.name = name; … … 939 1042 {func:func, e:e, type:typeof e}); 940 1043 941 for (var prop in required_props) 942 { 1044 for (var prop in required_props) { 943 1045 assert(typeof e == "object" && prop in e && e[prop] == required_props[prop], 944 1046 "assert_throws", description, … … 956 1058 expose(assert_unreached, "assert_unreached"); 957 1059 958 function assert_any(assert_func, actual, expected_array) 1060 function assert_any(assert_func, actual, expected_array) 959 1061 { 960 1062 var args = [].slice.call(arguments, 3) 961 1063 var errors = [] 962 1064 var passed = false; 963 forEach(expected_array, 1065 forEach(expected_array, 964 1066 function(expected) 965 1067 { … … 967 1069 assert_func.apply(this, [actual, expected].concat(args)) 968 1070 passed = true; 969 } catch (e) {1071 } catch (e) { 970 1072 errors.push(e.message); 971 1073 } … … 980 1082 { 981 1083 this.name = name; 1084 1085 this.phases = { 1086 INITIAL:0, 1087 STARTED:1, 1088 HAS_RESULT:2, 1089 COMPLETE:3 1090 }; 1091 this.phase = this.phases.INITIAL; 1092 982 1093 this.status = this.NOTRUN; 983 1094 this.timeout_id = null; 984 this.is_done = false;985 1095 986 1096 this.properties = properties; 987 this.timeout_length = properties.timeout ? properties.timeout : settings.test_timeout; 1097 var timeout = properties.timeout ? properties.timeout : settings.test_timeout 1098 if (timeout != null) { 1099 this.timeout_length = timeout * tests.timeout_multiplier; 1100 } else { 1101 this.timeout_length = null; 1102 } 988 1103 989 1104 this.message = null; … … 991 1106 var this_obj = this; 992 1107 this.steps = []; 1108 1109 this.cleanup_callbacks = []; 993 1110 994 1111 tests.push(this); … … 1006 1123 Test.prototype.structured_clone = function() 1007 1124 { 1008 if(!this._structured_clone) 1009 { 1125 if (!this._structured_clone) { 1010 1126 var msg = this.message; 1011 1127 msg = msg ? String(msg) : msg; … … 1021 1137 Test.prototype.step = function(func, this_obj) 1022 1138 { 1023 //In case the test has already failed 1024 if (this.status !== this.NOTRUN) 1025 { 1026 return; 1027 } 1139 if (this.phase > this.phases.STARTED) { 1140 return; 1141 } 1142 this.phase = this.phases.STARTED; 1143 //If we don't get a result before the harness times out that will be a test timout 1144 this.set_status(this.TIMEOUT, "Test timed out"); 1028 1145 1029 1146 tests.started = true; … … 1035 1152 this.steps.push(func); 1036 1153 1037 if (arguments.length === 1) 1038 { 1154 if (arguments.length === 1) { 1039 1155 this_obj = this; 1040 1156 } 1041 1157 1042 try 1043 { 1044 func.apply(this_obj, Array.prototype.slice.call(arguments, 2)); 1045 } 1046 catch(e) 1047 { 1048 //This can happen if something called synchronously invoked another 1049 //step 1050 if (this.status !== this.NOTRUN) 1051 { 1158 try { 1159 return func.apply(this_obj, Array.prototype.slice.call(arguments, 2)); 1160 } catch (e) { 1161 if (this.phase >= this.phases.HAS_RESULT) { 1052 1162 return; 1053 1163 } 1054 this.status = this.FAIL; 1055 this.message = (typeof e === "object" && e !== null) ? e.message : e; 1164 var message = (typeof e === "object" && e !== null) ? e.message : e; 1056 1165 if (typeof e.stack != "undefined" && typeof e.message == "string") { 1057 1166 //Try to make it more informative for some exceptions, at least … … 1059 1168 //just errors like "Cannot read property 'parentNode' of null" 1060 1169 //or "root is null". Makes it a lot longer, of course. 1061 this.message += "(stack: " + e.stack + ")"; 1062 } 1170 message += "(stack: " + e.stack + ")"; 1171 } 1172 this.set_status(this.FAIL, message); 1173 this.phase = this.phases.HAS_RESULT; 1063 1174 this.done(); 1064 if (debug && e.constructor !== AssertionError) {1065 throw e;1066 }1067 1175 } 1068 1176 }; … … 1072 1180 var test_this = this; 1073 1181 1074 if (arguments.length === 1) 1075 { 1182 if (arguments.length === 1) { 1076 1183 this_obj = test_this; 1077 1184 } … … 1088 1195 var test_this = this; 1089 1196 1090 if (arguments.length === 1) 1091 { 1197 if (arguments.length === 1) { 1092 1198 this_obj = test_this; 1093 1199 } … … 1095 1201 return function() 1096 1202 { 1097 test_this.step.apply(test_this, [func, this_obj].concat( 1098 Array.prototype.slice.call(arguments))); 1203 if (func) { 1204 test_this.step.apply(test_this, [func, this_obj].concat( 1205 Array.prototype.slice.call(arguments))); 1206 } 1099 1207 test_this.done(); 1100 1208 }; 1101 }; 1209 } 1210 1211 Test.prototype.add_cleanup = function(callback) { 1212 this.cleanup_callbacks.push(callback); 1213 } 1102 1214 1103 1215 Test.prototype.set_timeout = function() 1104 1216 { 1105 var this_obj = this; 1106 this.timeout_id = setTimeout(function() 1107 { 1108 this_obj.timeout(); 1109 }, this.timeout_length); 1110 }; 1217 if (this.timeout_length !== null) { 1218 var this_obj = this; 1219 this.timeout_id = setTimeout(function() 1220 { 1221 this_obj.timeout(); 1222 }, this.timeout_length); 1223 } 1224 } 1225 1226 Test.prototype.set_status = function(status, message) 1227 { 1228 this.status = status; 1229 this.message = message; 1230 } 1111 1231 1112 1232 Test.prototype.timeout = function() 1113 1233 { 1114 this.status = this.TIMEOUT;1115 1234 this.timeout_id = null; 1116 this.message = "Test timed out"; 1235 this.set_status(this.TIMEOUT, "Test timed out") 1236 this.phase = this.phases.HAS_RESULT; 1117 1237 this.done(); 1118 1238 }; … … 1120 1240 Test.prototype.done = function() 1121 1241 { 1122 if (this. is_done) {1242 if (this.phase == this.phases.COMPLETE) { 1123 1243 return; 1124 1244 } 1245 1246 if (this.phase <= this.phases.STARTED) { 1247 this.set_status(this.PASS, null); 1248 } 1249 1250 if (this.status == this.NOTRUN) { 1251 alert(this.phase); 1252 } 1253 1254 this.phase = this.phases.COMPLETE; 1255 1125 1256 clearTimeout(this.timeout_id); 1126 if (this.status === this.NOTRUN)1127 {1128 this.status = this.PASS;1129 }1130 this.is_done = true;1131 1257 tests.result(this); 1132 }; 1133 1258 this.cleanup(); 1259 }; 1260 1261 Test.prototype.cleanup = function() { 1262 forEach(this.cleanup_callbacks, 1263 function(cleanup_callback) { 1264 cleanup_callback() 1265 }); 1266 } 1134 1267 1135 1268 /* … … 1153 1286 TestsStatus.prototype.structured_clone = function() 1154 1287 { 1155 if(!this._structured_clone) 1156 { 1288 if (!this._structured_clone) { 1157 1289 var msg = this.message; 1158 1290 msg = msg ? String(msg) : msg; … … 1186 1318 this.processing_callbacks = false; 1187 1319 1188 this.timeout_length = settings.timeout; 1320 this.allow_uncaught_exception = false; 1321 1322 this.timeout_multiplier = 1; 1323 this.timeout_length = this.get_timeout(); 1189 1324 this.timeout_id = null; 1190 1325 … … 1212 1347 Tests.prototype.setup = function(func, properties) 1213 1348 { 1214 if (this.phase >= this.phases.HAVE_RESULTS) 1215 { 1349 if (this.phase >= this.phases.HAVE_RESULTS) { 1216 1350 return; 1217 1351 } 1218 if (this.phase < this.phases.SETUP) 1219 {1352 1353 if (this.phase < this.phases.SETUP) { 1220 1354 this.phase = this.phases.SETUP; 1221 1355 } 1222 1356 1223 for (var p in properties) 1224 { 1225 if (properties.hasOwnProperty(p)) 1226 { 1227 this.properties[p] = properties[p]; 1228 } 1229 } 1230 1231 if (properties.timeout) 1232 { 1233 this.timeout_length = properties.timeout; 1234 } 1235 if (properties.explicit_done) 1236 { 1237 this.wait_for_finish = true; 1238 } 1239 if (properties.explicit_timeout) { 1240 this.timeout_length = null; 1241 } 1242 1243 if (func) 1244 { 1245 try 1246 { 1357 this.properties = properties; 1358 1359 for (var p in properties) { 1360 if (properties.hasOwnProperty(p)) { 1361 var value = properties[p] 1362 if (p == "allow_uncaught_exception") { 1363 this.allow_uncaught_exception = value; 1364 } else if (p == "explicit_done" && value) { 1365 this.wait_for_finish = true; 1366 } else if (p == "explicit_timeout" && value) { 1367 this.timeout_length = null; 1368 if (this.timeout_id) 1369 { 1370 clearTimeout(this.timeout_id); 1371 } 1372 } else if (p == "timeout_multiplier") { 1373 this.timeout_multiplier = value; 1374 } 1375 } 1376 } 1377 1378 if (func) { 1379 try { 1247 1380 func(); 1248 } catch(e) 1249 { 1381 } catch (e) { 1250 1382 this.status.status = this.status.ERROR; 1251 this.status.message = e;1383 this.status.message = String(e); 1252 1384 }; 1253 1385 } 1254 1386 this.set_timeout(); 1255 1387 }; 1388 1389 Tests.prototype.get_timeout = function() 1390 { 1391 var metas = document.getElementsByTagName("meta"); 1392 for (var i = 0; i < metas.length; i++) { 1393 if (metas[i].name == "timeout") { 1394 if (metas[i].content == "long") { 1395 return settings.harness_timeout.long; 1396 } 1397 break; 1398 } 1399 } 1400 return settings.harness_timeout.normal; 1401 } 1256 1402 1257 1403 Tests.prototype.set_timeout = function() … … 1259 1405 var this_obj = this; 1260 1406 clearTimeout(this.timeout_id); 1261 if (this.timeout_length !== null) 1262 { 1407 if (this.timeout_length !== null) { 1263 1408 this.timeout_id = setTimeout(function() { 1264 1409 this_obj.timeout(); … … 1309 1454 function(w, is_same_origin) 1310 1455 { 1311 if(is_same_origin && w.start_callback) 1312 { 1313 try 1314 { 1456 if (is_same_origin && w.start_callback) { 1457 try { 1315 1458 w.start_callback(this_obj.properties); 1316 } 1317 catch(e) 1318 { 1319 if (debug) 1320 { 1321 throw(e); 1459 } catch (e) { 1460 if (debug) { 1461 throw e; 1322 1462 } 1323 1463 } 1324 1464 } 1325 if (supports_post_message(w)) 1326 { 1465 if (supports_post_message(w) && w !== self) { 1327 1466 w.postMessage({ 1328 1467 type: "start", … … 1335 1474 Tests.prototype.result = function(test) 1336 1475 { 1337 if (this.phase > this.phases.HAVE_RESULTS) 1338 { 1476 if (this.phase > this.phases.HAVE_RESULTS) { 1339 1477 return; 1340 1478 } … … 1356 1494 function(w, is_same_origin) 1357 1495 { 1358 if(is_same_origin && w.result_callback) 1359 { 1360 try 1361 { 1496 if (is_same_origin && w.result_callback) { 1497 try { 1362 1498 w.result_callback(test); 1363 } 1364 catch(e) 1365 { 1366 if(debug) { 1499 } catch (e) { 1500 if (debug) { 1367 1501 throw e; 1368 1502 } 1369 1503 } 1370 1504 } 1371 if (supports_post_message(w)) 1372 { 1505 if (supports_post_message(w) && w !== self) { 1373 1506 w.postMessage({ 1374 1507 type: "result", … … 1378 1511 }); 1379 1512 this.processing_callbacks = false; 1380 if (this_obj.all_done()) 1381 { 1513 if (this_obj.all_done()) { 1382 1514 this_obj.complete(); 1383 1515 } … … 1393 1525 function(x) 1394 1526 { 1395 if(x.status === x.NOTRUN) 1396 { 1527 if (x.status === x.NOTRUN) { 1397 1528 this_obj.notify_result(x); 1529 x.cleanup(); 1398 1530 } 1399 1531 } … … 1411 1543 return test.structured_clone(); 1412 1544 }); 1413 if (this.status.status === null) 1414 { 1545 if (this.status.status === null) { 1415 1546 this.status.status = this.status.OK; 1416 1547 } … … 1425 1556 function(w, is_same_origin) 1426 1557 { 1427 if(is_same_origin && w.completion_callback) 1428 { 1429 try 1430 { 1558 if (is_same_origin && w.completion_callback) { 1559 try { 1431 1560 w.completion_callback(this_obj.tests, this_obj.status); 1432 } 1433 catch(e) 1434 { 1435 if (debug) 1436 { 1561 } catch (e) { 1562 if (debug) { 1437 1563 throw e; 1438 1564 } 1439 1565 } 1440 1566 } 1441 if (supports_post_message(w)) 1442 { 1567 if (supports_post_message(w) && w !== self) { 1443 1568 w.postMessage({ 1444 1569 type: "complete", … … 1452 1577 var tests = new Tests(); 1453 1578 1579 window.onerror = function(msg) { 1580 if (!tests.allow_uncaught_exception) { 1581 tests.status.status = tests.status.ERROR; 1582 tests.status.message = msg; 1583 tests.complete(); 1584 } 1585 } 1586 1454 1587 function timeout() { 1455 if (tests.timeout_length === null) 1456 { 1588 if (tests.timeout_length === null) { 1457 1589 tests.timeout(); 1458 1590 } … … 1483 1615 1484 1616 function Output() { 1485 this.output_document = document;1486 this.output_node = null;1487 this.done_count = 0;1488 this.enabled = settings.output;1489 this.phase = this.INITIAL;1617 this.output_document = document; 1618 this.output_node = null; 1619 this.done_count = 0; 1620 this.enabled = settings.output; 1621 this.phase = this.INITIAL; 1490 1622 } 1491 1623 … … 1522 1654 { 1523 1655 var output_document; 1524 if (typeof this.output_document === "function") 1525 { 1656 if (typeof this.output_document === "function") { 1526 1657 output_document = this.output_document.apply(undefined); 1527 } else 1528 { 1658 } else { 1529 1659 output_document = this.output_document; 1530 1660 } 1531 if (!output_document) 1532 { 1661 if (!output_document) { 1533 1662 return; 1534 1663 } 1535 1664 var node = output_document.getElementById("log"); 1536 if (node) 1537 { 1665 if (node) { 1538 1666 this.output_document = output_document; 1539 1667 this.output_node = node; … … 1543 1671 Output.prototype.show_status = function(test) 1544 1672 { 1545 if (this.phase < this.STARTED) 1546 { 1673 if (this.phase < this.STARTED) { 1547 1674 this.init(); 1548 1675 } 1549 if (!this.enabled) 1550 { 1676 if (!this.enabled) { 1551 1677 return; 1552 1678 } 1553 if (this.phase < this.HAVE_RESULTS) 1554 { 1679 if (this.phase < this.HAVE_RESULTS) { 1555 1680 this.resolve_log(); 1556 1681 this.phase = this.HAVE_RESULTS; 1557 1682 } 1558 1683 this.done_count++; 1559 if (this.output_node) 1560 { 1684 if (this.output_node) { 1561 1685 if (this.done_count < 100 1562 1686 || (this.done_count < 1000 && this.done_count % 100 == 0) … … 1574 1698 return; 1575 1699 } 1576 if (!this.enabled) 1577 { 1700 if (!this.enabled) { 1578 1701 return; 1579 1702 } … … 1584 1707 1585 1708 var log = this.output_node; 1586 if (!log) 1587 { 1709 if (!log) { 1588 1710 return; 1589 1711 } 1590 1712 var output_document = this.output_document; 1591 1713 1592 while (log.lastChild) 1593 { 1714 while (log.lastChild) { 1594 1715 log.removeChild(log.lastChild); 1595 1716 } … … 1605 1726 } 1606 1727 1728 var status_text_harness = {}; 1729 status_text_harness[harness_status.OK] = "OK"; 1730 status_text_harness[harness_status.ERROR] = "Error"; 1731 status_text_harness[harness_status.TIMEOUT] = "Timeout"; 1732 1607 1733 var status_text = {}; 1608 1734 status_text[Test.prototype.PASS] = "Pass"; … … 1612 1738 1613 1739 var status_number = {}; 1614 forEach(tests, function(test) { 1740 forEach(tests, 1741 function(test) { 1615 1742 var status = status_text[test.status]; 1616 if (status_number.hasOwnProperty(status)) 1617 { 1743 if (status_number.hasOwnProperty(status)) { 1618 1744 status_number[status] += 1; 1619 1745 } else { … … 1629 1755 var summary_template = ["section", {"id":"summary"}, 1630 1756 ["h2", {}, "Summary"], 1757 function(vars) 1758 { 1759 if (harness_status.status === harness_status.OK) { 1760 return null; 1761 } 1762 1763 var status = status_text_harness[harness_status.status]; 1764 var rv = [["p", {"class":status_class(status)}]]; 1765 1766 if (harness_status.status === harness_status.ERROR) { 1767 rv[0].push("Harness encountered an error:"); 1768 rv.push(["pre", {}, harness_status.message]); 1769 } else if (harness_status.status === harness_status.TIMEOUT) { 1770 rv[0].push("Harness timed out."); 1771 } else { 1772 rv[0].push("Harness got an unexpected status."); 1773 } 1774 1775 return rv; 1776 }, 1631 1777 ["p", {}, "Found ${num_tests} tests"], 1632 1778 function(vars) { 1633 1779 var rv = [["div", {}]]; 1634 var i =0;1780 var i = 0; 1635 1781 while (status_text.hasOwnProperty(i)) { 1636 1782 if (status_number.hasOwnProperty(status_text[i])) { … … 1654 1800 function(e) 1655 1801 { 1656 if (output_document.getElementById("results") === null) 1657 { 1802 if (output_document.getElementById("results") === null) { 1658 1803 e.preventDefault(); 1659 1804 return; … … 1694 1839 return false; 1695 1840 } 1696 1841 1697 1842 function get_assertion(test) 1698 1843 { … … 1705 1850 return ''; 1706 1851 } 1707 1852 1708 1853 log.appendChild(document.createElementNS(xhtml_ns, "section")); 1709 1854 var assertions = has_assertions(); … … 1783 1928 if (typeof template === "function") { 1784 1929 var replacement = template(substitutions); 1785 if (replacement) 1786 { 1787 var rv = substitute(replacement, substitutions); 1788 return rv; 1789 } 1790 else 1791 { 1930 if (!replacement) { 1792 1931 return null; 1793 1932 } 1794 } 1795 else if (is_single_node(template)) 1796 { 1933 1934 return substitute(replacement, substitutions); 1935 } 1936 1937 if (is_single_node(template)) { 1797 1938 return substitute_single(template, substitutions); 1798 1939 } 1799 else 1800 { 1801 return filter(map(template, function(x) { 1802 return substitute(x, substitutions); 1803 }), function(x) {return x !== null;}); 1804 } 1940 1941 return filter(map(template, function(x) { 1942 return substitute(x, substitutions); 1943 }), function(x) {return x !== null;}); 1805 1944 } 1806 1945 … … 1812 1951 var components = input.split(substitution_re); 1813 1952 var rv = []; 1814 for (var i=0; i<components.length; i+=2) 1815 { 1953 for (var i = 0; i < components.length; i += 2) { 1816 1954 rv.push(components[i]); 1817 if (components[i+1]) 1818 { 1819 rv.push(String(substitutions[components[i+1]])); 1955 if (components[i + 1]) { 1956 rv.push(String(substitutions[components[i + 1]])); 1820 1957 } 1821 1958 } … … 1836 1973 { 1837 1974 rv[1] = {}; 1838 for (var name in template[1]) 1839 { 1840 if (attrs.hasOwnProperty(name)) 1841 { 1975 for (var name in template[1]) { 1976 if (attrs.hasOwnProperty(name)) { 1842 1977 var new_name = do_substitution(name).join(""); 1843 1978 var new_value = do_substitution(attrs[name]).join(""); … … 1849 1984 function substitute_children(children, rv) 1850 1985 { 1851 for (var i=0; i<children.length; i++) 1852 { 1986 for (var i = 0; i < children.length; i++) { 1853 1987 if (children[i] instanceof Object) { 1854 1988 var replacement = substitute(children[i], substitutions); 1855 if (replacement !== null) 1856 { 1857 if (is_single_node(replacement)) 1858 { 1989 if (replacement !== null) { 1990 if (is_single_node(replacement)) { 1859 1991 rv.push(replacement); 1860 } 1861 else 1862 { 1992 } else { 1863 1993 extend(rv, replacement); 1864 1994 } 1865 1995 } 1866 } 1867 else 1868 { 1996 } else { 1869 1997 extend(rv, do_substitution(String(children[i]))); 1870 1998 } … … 1876 2004 } 1877 2005 1878 function make_dom_single(template, doc) 1879 { 1880 var output_document = doc || document; 1881 if (template[0] === "{text}") 1882 { 1883 var element = output_document.createTextNode(""); 1884 for (var i=1; i<template.length; i++) 1885 { 1886 element.data += template[i]; 1887 } 1888 } 1889 else 1890 { 1891 var element = output_document.createElementNS(xhtml_ns, template[0]); 1892 for (var name in template[1]) { 1893 if (template[1].hasOwnProperty(name)) 1894 { 1895 element.setAttribute(name, template[1][name]); 1896 } 1897 } 1898 for (var i=2; i<template.length; i++) 1899 { 1900 if (template[i] instanceof Object) 1901 { 1902 var sub_element = make_dom(template[i]); 1903 element.appendChild(sub_element); 1904 } 1905 else 1906 { 1907 var text_node = output_document.createTextNode(template[i]); 1908 element.appendChild(text_node); 1909 } 1910 } 1911 } 1912 1913 return element; 1914 } 1915 1916 1917 1918 function make_dom(template, substitutions, output_document) 1919 { 1920 if (is_single_node(template)) 1921 { 2006 function make_dom_single(template, doc) 2007 { 2008 var output_document = doc || document; 2009 if (template[0] === "{text}") { 2010 var element = output_document.createTextNode(""); 2011 for (var i = 1; i < template.length; i++) { 2012 element.data += template[i]; 2013 } 2014 } else { 2015 var element = output_document.createElementNS(xhtml_ns, template[0]); 2016 for (var name in template[1]) { 2017 if (template[1].hasOwnProperty(name)) { 2018 element.setAttribute(name, template[1][name]); 2019 } 2020 } 2021 for (var i = 2; i < template.length; i++) { 2022 if (template[i] instanceof Object) { 2023 var sub_element = make_dom(template[i]); 2024 element.appendChild(sub_element); 2025 } else { 2026 var text_node = output_document.createTextNode(template[i]); 2027 element.appendChild(text_node); 2028 } 2029 } 2030 } 2031 2032 return element; 2033 } 2034 2035 2036 2037 function make_dom(template, substitutions, output_document) 2038 { 2039 if (is_single_node(template)) { 1922 2040 return make_dom_single(template, output_document); 1923 2041 } 1924 else 1925 { 1926 return map(template, function(x) { 1927 return make_dom_single(x, output_document); 1928 }); 1929 } 1930 } 1931 1932 function render(template, substitutions, output_document) 2042 2043 return map(template, function(x) { 2044 return make_dom_single(x, output_document); 2045 }); 2046 } 2047 2048 function render(template, substitutions, output_document) 1933 2049 { 1934 2050 return make_dom(substitute(template, substitutions), output_document); … … 1940 2056 function assert(expected_true, function_name, description, error, substitutions) 1941 2057 { 1942 if (expected_true !== true) 1943 { 2058 if (expected_true !== true) { 1944 2059 throw new AssertionError(make_message(function_name, description, 1945 2060 error, substitutions)); … … 1968 2083 function filter(array, callable, thisObj) { 1969 2084 var rv = []; 1970 for (var i=0; i<array.length; i++) 1971 { 1972 if (array.hasOwnProperty(i)) 1973 { 2085 for (var i = 0; i < array.length; i++) { 2086 if (array.hasOwnProperty(i)) { 1974 2087 var pass = callable.call(thisObj, array[i], i, array); 1975 2088 if (pass) { … … 1985 2098 var rv = []; 1986 2099 rv.length = array.length; 1987 for (var i=0; i<array.length; i++) 1988 { 1989 if (array.hasOwnProperty(i)) 1990 { 2100 for (var i = 0; i < array.length; i++) { 2101 if (array.hasOwnProperty(i)) { 1991 2102 rv[i] = callable.call(thisObj, array[i], i, array); 1992 2103 } … … 2002 2113 function forEach (array, callback, thisObj) 2003 2114 { 2004 for (var i=0; i<array.length; i++) 2005 { 2006 if (array.hasOwnProperty(i)) 2007 { 2115 for (var i = 0; i < array.length; i++) { 2116 if (array.hasOwnProperty(i)) { 2008 2117 callback.call(thisObj, array[i], i, array); 2009 2118 } … … 2015 2124 var rv = {}; 2016 2125 var p; 2017 for (p in a) 2018 { 2126 for (p in a) { 2019 2127 rv[p] = a[p]; 2020 2128 } … … 2029 2137 var components = name.split("."); 2030 2138 var target = window; 2031 for (var i=0; i<components.length - 1; i++) 2032 { 2033 if (!(components[i] in target)) 2034 { 2139 for (var i = 0; i < components.length - 1; i++) { 2140 if (!(components[i] in target)) { 2035 2141 target[components[i]] = {}; 2036 2142 } … … 2052 2158 var so; 2053 2159 var origins = location.ancestorOrigins; 2054 while (w != w.parent) 2055 { 2160 while (w != w.parent) { 2056 2161 w = w.parent; 2057 2162 // In WebKit, calls to parent windows' properties that aren't on the same … … 2066 2171 // the origins of enclosing windows. See: 2067 2172 // http://trac.webkit.org/changeset/113945. 2068 if (origins) {2173 if (origins) { 2069 2174 so = (location.origin == origins[i]); 2070 } 2071 else 2072 { 2175 } else { 2073 2176 so = is_same_origin(w); 2074 2177 } … … 2077 2180 } 2078 2181 w = window.opener; 2079 if(w) 2080 { 2182 if (w) { 2081 2183 // window.opener isn't included in the `location.ancestorOrigins` prop. 2082 2184 // We'll just have to deal with a simple check and an error msg on WebKit … … 2098 2200 'random_prop' in w; 2099 2201 return true; 2100 } catch (e) {2202 } catch (e) { 2101 2203 return false; 2102 2204 } … … 2115 2217 // browser. So just doing an existence test here won't do, you also need 2116 2218 // to wrap it in a try..cacth block. 2117 try 2118 { 2219 try { 2119 2220 type = typeof w.postMessage; 2120 if (type === "function") 2121 { 2221 if (type === "function") { 2122 2222 supports = true; 2123 2223 } 2224 2124 2225 // IE8 supports postMessage, but implements it as a host object which 2125 2226 // returns "object" as its `typeof`. 2126 else if (type === "object") 2127 { 2227 else if (type === "object") { 2128 2228 supports = true; 2129 2229 } 2230 2130 2231 // This is the case where postMessage isn't supported AND accessing a 2131 2232 // window property across origins does NOT throw (e.g. old Safari browser). 2132 else 2133 { 2233 else { 2134 2234 supports = false; 2135 2235 } 2136 } 2137 catch(e) { 2236 } catch (e) { 2138 2237 // This is the case where postMessage isn't supported AND accessing a 2139 2238 // window property across origins throws (e.g. old Firefox browser). -
trunk/Source/WebCore/ChangeLog
r171032 r171033 1 2014-07-11 Jer Noble <jer.noble@apple.com> 2 3 [MSE] http/tests/media/media-source/mediasource-duration.html is failing. 4 https://bugs.webkit.org/show_bug.cgi?id=134852 5 6 Reviewed by Eric Carlson. 7 8 Fixes the following tests: 9 http/tests/media/media-source/mediasource-config-change-mp4-a-bitrate.html 10 http/tests/media/media-source/mediasource-config-change-mp4-av-audio-bitrate.html 11 http/tests/media/media-source/mediasource-config-change-mp4-av-video-bitrate.html 12 http/tests/media/media-source/mediasource-config-change-mp4-v-bitrate.html 13 http/tests/media/media-source/mediasource-config-change-mp4-v-framerate.html 14 http/tests/media/media-source/mediasource-duration.html 15 http/tests/media/media-source/mediasource-play.html 16 17 The primary change necessary to fix the mediasource-duration.html test was to add support 18 for delaying the completion of a seek operation until the HTMLMediaElement's readyState 19 rises to > HAVE_CURRENT_DATA. This is accomplished by modifying MediaSourcePrivate to have 20 waitForSeekCompleted() and seekCompleted() virtual methods. These are called by MediaSource 21 when a seek operation results in the current time moving outside the currently buffered time 22 ranges, and when an append operation results in the readyState changing, respectively. 23 24 A number of other drive-by fixes were necessary to get this test fully passing, as noted 25 below. 26 27 Make the MediaSource the primary owner of the media's duration, rather than the MediaSourcePrivate. 28 Move the MediaSourcePrivateClient pointer to the MediaSourcePrivate from the MediaPlayerPrivate, so 29 the MediaSource's duration can be retrieved. While we're at it, do the same thing for buffered. 30 31 * Modules/mediasource/MediaSource.cpp: 32 (WebCore::MediaSource::MediaSource): Initialize m_duration. 33 (WebCore::MediaSource::duration): Simple accessor. 34 (WebCore::MediaSource::setDurationInternal): Bring 'duration change algorithm' up to spec. 35 (WebCore::MediaSource::setReadyState): Reset m_duration on close. 36 * Modules/mediasource/MediaSource.h: 37 * platform/graphics/MediaSourcePrivate.h: 38 * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm: 39 (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::load): Do not call setPrivateAndOpen(). 40 (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::durationDouble): Pass through to MediaSourcePrivateAVFObjC. 41 (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::buffered): Ditto. 42 * platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h: 43 * platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm: 44 (WebCore::MediaSourcePrivateAVFObjC::create): Call setPrivateAndOpen(). 45 (WebCore::MediaSourcePrivateAVFObjC::MediaSourcePrivateAVFObjC): Set m_client. 46 (WebCore::MediaSourcePrivateAVFObjC::duration): Pass through to MediaSourcePrivateClient. 47 (WebCore::MediaSourcePrivateAVFObjC::buffered): Ditto. 48 (WebCore::MediaSourcePrivateAVFObjC::durationChanged): Pass through to MediaPlayerPrivateMediaSourceAVFObjC. 49 (WebCore::MediaSourcePrivateAVFObjC::setDuration): Deleted. 50 * platform/graphics/gstreamer/MediaSourceGStreamer.cpp: 51 (WebCore::MediaSourceGStreamer::open): Pass in MediaSourcePrivateClient. 52 (WebCore::MediaSourceGStreamer::MediaSourceGStreamer): Initialize m_mediaSource. 53 (WebCore::MediaSourceGStreamer::durationChanged): Retrieve the duration from MediaSourcePrivateClient. 54 (WebCore::MediaSourceGStreamer::markEndOfStream): Remove unnecssary ASSERT. 55 (WebCore::MediaSourceGStreamer::unmarkEndOfStream): Ditto. 56 (WebCore::MediaSourceGStreamer::setDuration): Deleted. 57 * platform/graphics/gstreamer/MediaSourceGStreamer.h: 58 * platform/mock/mediasource/MockMediaPlayerMediaSource.cpp: 59 (WebCore::MockMediaPlayerMediaSource::load): Do not call setPrivateAndOpen(). 60 (WebCore::MockMediaPlayerMediaSource::buffered): Pass through to MockMediaSourcePrivate. 61 (WebCore::MockMediaPlayerMediaSource::durationDouble): Ditto. 62 (WebCore::MockMediaPlayerMediaSource::advanceCurrentTime): Ditto. 63 * platform/mock/mediasource/MockMediaSourcePrivate.cpp: 64 (WebCore::MockMediaSourcePrivate::create): Call setPrivateAndOpen(). 65 (WebCore::MockMediaSourcePrivate::MockMediaSourcePrivate): Set m_client. 66 (WebCore::MockMediaSourcePrivate::duration): Pass through to MediaSourcePrivateClient. 67 (WebCore::MockMediaSourcePrivate::buffered): Ditto. 68 (WebCore::MockMediaSourcePrivate::durationChanged): Pass thorugh to MockMediaPlayerMediaSource. 69 (WebCore::MockMediaSourcePrivate::setDuration): Deleted. 70 71 Route seekToTime through MediaSource, rather than through MediaSourcePrivate, so that 72 the time can be compared against the buffered ranges, and trigger the delay of the seek 73 operation if necessary. Add a seekTimer to MediaPlayerPrivateMediaSourceAVFObjC, as this 74 guarantees the order of asynchronous operations, rather than callOnMainThread, which can 75 cause async operations to occur out of order. 76 77 * Modules/mediasource/MediaSource.cpp: 78 (WebCore::MediaSource::seekToTime): Bring up to spec. 79 (WebCore::MediaSource::completeSeek): Ditto. 80 (WebCore::MediaSource::monitorSourceBuffers): Call completeSeek() when appropriate. 81 * Modules/mediasource/SourceBuffer.cpp: 82 (WebCore::SourceBuffer::sourceBufferPrivateSeekToTime): Deleted. 83 (WebCore::SourceBuffer::seekToTime): Renamed from sourceBufferPrivateSeekToTime(). 84 * platform/graphics/MediaSourcePrivate.h: 85 * platform/graphics/MediaSourcePrivateClient.h: 86 * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h: 87 * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm: 88 (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::MediaPlayerPrivateMediaSourceAVFObjC): Add seekTimer. Only 89 call timeChanged() if no longer seeking, thereby triggering a 'seeked' event. 90 (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::~MediaPlayerPrivateMediaSourceAVFObjC): Clear m_seekTimer. 91 (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::seekWithTolerance): Use m_seekTimer. 92 (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::seekTimerFired): Call seekInternal. 93 (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::seekInternal): Add logging. 94 (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::waitForSeekCompleted): Added. 95 (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::seekCompleted): Added; trigger 'seeked'. 96 (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::setReadyState): No longer attempt to finish seek when 97 readyState changes here; this has been moved up to MediaSource.cpp. 98 * platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h: 99 * platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm: 100 (WebCore::MediaSourcePrivateAVFObjC::waitForSeekCompleted): Pass through to MediaPlayerPrivateMediaSourceAVFObjC. 101 (WebCore::MediaSourcePrivateAVFObjC::seekCompleted): Ditto. 102 (WebCore::MediaSourcePrivateAVFObjC::seekToTime): Pass through to MediaSourcePrivateClient. 103 (WebCore::MediaSourcePrivateAVFObjC::fastSeekTimeForMediaTime): Ditto. 104 * platform/mock/mediasource/MockMediaPlayerMediaSource.cpp: 105 (WebCore::MockMediaPlayerMediaSource::MockMediaPlayerMediaSource): Initialize m_seekCompleted. 106 (WebCore::MockMediaPlayerMediaSource::seeking): Check for an uncompleted seek operation. 107 (WebCore::MockMediaPlayerMediaSource::seekWithTolerance): Ditto. 108 (WebCore::MockMediaPlayerMediaSource::waitForSeekCompleted): Added. 109 (WebCore::MockMediaPlayerMediaSource::seekCompleted): Added; trigger 'seeked'. 110 * platform/mock/mediasource/MockMediaPlayerMediaSource.h: 111 * platform/mock/mediasource/MockMediaSourcePrivate.cpp: 112 (WebCore::MockMediaSourcePrivate::waitForSeekCompleted): Pass through to MockMediaPlayerMediaSource. 113 (WebCore::MockMediaSourcePrivate::seekCompleted): Ditto. 114 * platform/mock/mediasource/MockMediaSourcePrivate.h: 115 116 Drive-by fixes. 117 118 * Modules/mediasource/MediaSource.cpp: 119 (WebCore::MediaSource::streamEndedWithError): Re-order the steps in streamEndedWithError() 120 to avoid the MediaSource being closed and re-opened by the resulting duration change 121 operation. 122 * Modules/mediasource/MediaSource.h: 123 * Modules/mediasource/SourceBuffer.cpp: 124 (WebCore::SourceBuffer::remove): Added logging. 125 (WebCore::SourceBuffer::removeCodedFrames): Ditto. 126 (WebCore::SourceBuffer::hasFutureTime): Swap an ASSERT for an early-return; it's possible 127 for currentTime() to be outside of a buffered area. 128 * Modules/mediasource/SourceBuffer.h: 129 * html/HTMLMediaElement.cpp: 130 (WebCore::HTMLMediaElement::parseAttribute): Do not issue an additional 'timeupdate' event 131 after finishSeek() issues one of its own. 132 * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm: 133 (WebCore::globalDataParserQueue): Allow parsing operations to happen concurrently on 134 background queues. 135 1 136 2014-07-12 Eric Carlson <eric.carlson@apple.com> 2 137 -
trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp
r171017 r171033 77 77 : ActiveDOMObject(&context) 78 78 , m_mediaElement(0) 79 , m_duration(std::numeric_limits<double>::quiet_NaN()) 80 , m_pendingSeekTime(MediaTime::invalidTime()) 79 81 , m_readyState(closedKeyword()) 80 82 , m_asyncEventQueue(*this) … … 129 131 double MediaSource::duration() const 130 132 { 131 return isClosed() ? std::numeric_limits<float>::quiet_NaN() : m_private->duration().toDouble();133 return m_duration; 132 134 } 133 135 … … 179 181 180 182 return PlatformTimeRanges::create(intersectionRanges->ranges()); 183 } 184 185 void MediaSource::seekToTime(const MediaTime& time) 186 { 187 // 2.4.3 Seeking 188 // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#mediasource-seeking 189 190 m_pendingSeekTime = time; 191 192 // Run the following steps as part of the "Wait until the user agent has established whether or not the 193 // media data for the new playback position is available, and, if it is, until it has decoded enough data 194 // to play back that position" step of the seek algorithm: 195 // 1. The media element looks for media segments containing the new playback position in each SourceBuffer 196 // object in activeSourceBuffers. 197 for (auto& sourceBuffer : *m_activeSourceBuffers) { 198 // ↳ If one or more of the objects in activeSourceBuffers is missing media segments for the new 199 // playback position 200 if (!sourceBuffer->buffered()->ranges().contain(time)) { 201 // 1.1 Set the HTMLMediaElement.readyState attribute to HAVE_METADATA. 202 m_private->setReadyState(MediaPlayer::HaveMetadata); 203 204 // 1.2 The media element waits until an appendBuffer() or an appendStream() call causes the coded 205 // frame processing algorithm to set the HTMLMediaElement.readyState attribute to a value greater 206 // than HAVE_METADATA. 207 LOG(MediaSource, "MediaSource::seekToTime(%p) - waitForSeekCompleted()", this); 208 m_private->waitForSeekCompleted(); 209 return; 210 } 211 // ↳ Otherwise 212 // Continue 213 } 214 215 completeSeek(); 216 } 217 218 void MediaSource::completeSeek() 219 { 220 // 2.4.3 Seeking, ctd. 221 // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#mediasource-seeking 222 223 ASSERT(m_pendingSeekTime.isValid()); 224 225 // 2. The media element resets all decoders and initializes each one with data from the appropriate 226 // initialization segment. 227 // 3. The media element feeds coded frames from the active track buffers into the decoders starting 228 // with the closest random access point before the new playback position. 229 for (auto& sourceBuffer : *m_activeSourceBuffers) 230 sourceBuffer->seekToTime(m_pendingSeekTime); 231 232 // 4. Resume the seek algorithm at the "Await a stable state" step. 233 m_private->seekCompleted(); 234 235 m_pendingSeekTime = MediaTime::invalidTime(); 236 monitorSourceBuffers(); 181 237 } 182 238 … … 218 274 m_private->setReadyState(MediaPlayer::HaveEnoughData); 219 275 276 if (m_pendingSeekTime.isValid()) 277 completeSeek(); 278 220 279 // 4. Abort these steps. 221 280 return; … … 232 291 m_private->setReadyState(MediaPlayer::HaveFutureData); 233 292 293 if (m_pendingSeekTime.isValid()) 294 completeSeek(); 295 234 296 // 4. Abort these steps. 235 297 return; … … 247 309 // advance the media timeline. 248 310 m_private->setReadyState(MediaPlayer::HaveCurrentData); 249 311 312 if (m_pendingSeekTime.isValid()) 313 completeSeek(); 314 250 315 // 4. Abort these steps. 251 316 } … … 284 349 void MediaSource::setDurationInternal(double duration) 285 350 { 286 m_private->setDuration(MediaTime::createWithDouble(duration)); 287 } 288 351 // Duration Change Algorithm 352 // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#duration-change-algorithm 353 354 // 1. If the current value of duration is equal to new duration, then return. 355 if (duration == m_duration) 356 return; 357 358 // 2. Set old duration to the current value of duration. 359 double oldDuration = m_duration; 360 361 // 3. Update duration to new duration. 362 m_duration = duration; 363 364 // 4. If the new duration is less than old duration, then call remove(new duration, old duration) 365 // on all objects in sourceBuffers. 366 if (!isnan(oldDuration) && duration < oldDuration) { 367 for (auto& sourceBuffer : *m_sourceBuffers) 368 sourceBuffer->remove(duration, oldDuration, IGNORE_EXCEPTION); 369 } 370 371 // 5. If a user agent is unable to partially render audio frames or text cues that start before and end after the 372 // duration, then run the following steps: 373 // 5.1 Update new duration to the highest end time reported by the buffered attribute across all SourceBuffer objects 374 // in sourceBuffers. 375 // 5.2 Update duration to new duration. 376 // NOTE: Assume UA is able to partially render audio frames. 377 378 // 6. Update the media controller duration to new duration and run the HTMLMediaElement duration change algorithm. 379 LOG(MediaSource, "MediaSource::setDurationInternal(%p) - duration(%g)", this, duration); 380 m_private->durationChanged(); 381 } 289 382 290 383 void MediaSource::setReadyState(const AtomicString& state) … … 298 391 m_private.clear(); 299 392 m_mediaElement = 0; 393 m_duration = std::numeric_limits<double>::quiet_NaN(); 300 394 } 301 395 … … 345 439 346 440 // 2.4.7 https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#end-of-stream-algorithm 347 // 1. Change the readyState attribute value to "ended".348 // 2. Queue a task to fire a simple event named sourceended at the MediaSource.349 setReadyState(endedKeyword());350 441 351 442 // 3. 352 443 if (error.isEmpty()) { 353 444 // ↳ If error is not set, is null, or is an empty string 354 // 1. Run the duration change algorithm with new duration set to the highest end timestamp 355 // across all SourceBuffer objects in sourceBuffers. 356 MediaTime maxEndTimestamp; 357 for (auto it = m_sourceBuffers->begin(), end = m_sourceBuffers->end(); it != end; ++it) 358 maxEndTimestamp = std::max((*it)->highestPresentationEndTimestamp(), maxEndTimestamp); 359 m_private->setDuration(maxEndTimestamp); 445 // 1. Run the duration change algorithm with new duration set to the highest end time reported by 446 // the buffered attribute across all SourceBuffer objects in sourceBuffers. 447 double maxEndTime = 0; 448 for (auto& sourceBuffer : *m_sourceBuffers) { 449 if (auto length = sourceBuffer->buffered()->length()) 450 maxEndTime = std::max(sourceBuffer->buffered()->end(length - 1, IGNORE_EXCEPTION), maxEndTime); 451 } 452 setDurationInternal(maxEndTime); 360 453 361 454 // 2. Notify the media element that it now has all of the media data. … … 397 490 ec = INVALID_ACCESS_ERR; 398 491 } 492 493 // NOTE: Do steps 1 & 2 after step 3 to avoid the MediaSource's readyState being re-opened by a 494 // remove() operation resulting from a duration change. 495 // FIXME: Re-number or update this section once <https://www.w3.org/Bugs/Public/show_bug.cgi?id=26316> is resolved. 496 // 1. Change the readyState attribute value to "ended". 497 // 2. Queue a task to fire a simple event named sourceended at the MediaSource. 498 setReadyState(endedKeyword()); 399 499 } 400 500 -
trunk/Source/WebCore/Modules/mediasource/MediaSource.h
r170932 r171033 73 73 virtual double duration() const override; 74 74 virtual std::unique_ptr<PlatformTimeRanges> buffered() const override; 75 virtual void seekToTime(const MediaTime&) override; 75 76 76 77 bool attachToElement(HTMLMediaElement*); … … 78 79 bool isClosed() const; 79 80 void monitorSourceBuffers(); 81 void completeSeek(); 80 82 81 83 void setDuration(double, ExceptionCode&); … … 128 130 RefPtr<SourceBufferList> m_activeSourceBuffers; 129 131 HTMLMediaElement* m_mediaElement; 132 double m_duration; 133 MediaTime m_pendingSeekTime; 130 134 AtomicString m_readyState; 131 135 GenericEventQueue m_asyncEventQueue; -
trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp
r171017 r171033 234 234 void SourceBuffer::remove(double start, double end, ExceptionCode& ec) 235 235 { 236 LOG(MediaSource, "SourceBuffer::remove(%p) - start(%s), end(%s)", this, toString(start).utf8().data(), toString(end).utf8().data()); 236 237 // Section 3.2 remove() method steps. 237 238 // 1. If start is negative or greater than duration, then throw an InvalidAccessError exception and abort these steps. … … 309 310 } 310 311 311 void SourceBuffer::s ourceBufferPrivateSeekToTime(SourceBufferPrivate*,const MediaTime& time)312 { 313 LOG(MediaSource, "SourceBuffer::s ourceBufferPrivateSeekToTime(%p) - time(%s)", this, toString(time).utf8().data());312 void SourceBuffer::seekToTime(const MediaTime& time) 313 { 314 LOG(MediaSource, "SourceBuffer::seekToTime(%p) - time(%s)", this, toString(time).utf8().data()); 314 315 315 316 for (auto& trackBufferPair : m_trackBufferMap) { … … 319 320 reenqueueMediaForTime(trackBuffer, trackID, time); 320 321 } 321 322 m_source->monitorSourceBuffers();323 322 } 324 323 … … 528 527 void SourceBuffer::removeCodedFrames(const MediaTime& start, const MediaTime& end) 529 528 { 529 LOG(MediaSource, "SourceBuffer::removeCodedFrames(%p) - start(%s), end(%s)", this, toString(start).utf8().data(), toString(end).utf8().data()); 530 530 531 // 3.5.9 Coded Frame Removal Algorithm 531 532 // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#sourcebuffer-coded-frame-removal … … 1450 1451 1451 1452 size_t found = ranges.find(nearest); 1452 ASSERT(found != notFound); 1453 if (found == notFound) 1454 return false; 1453 1455 1454 1456 bool ignoredValid = false; -
trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h
r170976 r171033 78 78 void removedFromMediaSource(); 79 79 const MediaTime& highestPresentationEndTimestamp() const { return m_highestPresentationEndTimestamp; } 80 void seekToTime(const MediaTime&); 80 81 81 82 #if ENABLE(VIDEO_TRACK) … … 117 118 virtual bool sourceBufferPrivateHasVideo(const SourceBufferPrivate*) const override; 118 119 virtual void sourceBufferPrivateDidBecomeReadyForMoreSamples(SourceBufferPrivate*, AtomicString trackID) override; 119 virtual void sourceBufferPrivateSeekToTime(SourceBufferPrivate*, const MediaTime&);120 120 virtual MediaTime sourceBufferPrivateFastSeekTimeForMediaTime(SourceBufferPrivate*, const MediaTime&, const MediaTime& negativeThreshold, const MediaTime& positiveThreshold); 121 121 virtual void sourceBufferPrivateAppendComplete(SourceBufferPrivate*, AppendResult) override; -
trunk/Source/WebCore/html/HTMLMediaElement.cpp
r170920 r171033 4092 4092 // it will only queue a 'timeupdate' event if we haven't already posted one at the current 4093 4093 // movie time. 4094 scheduleTimeupdateEvent(false); 4094 else 4095 scheduleTimeupdateEvent(false); 4095 4096 4096 4097 double now = currentTime(); -
trunk/Source/WebCore/platform/graphics/MediaSourcePrivate.h
r169536 r171033 52 52 enum AddStatus { Ok, NotSupported, ReachedIdLimit }; 53 53 virtual AddStatus addSourceBuffer(const ContentType&, RefPtr<SourceBufferPrivate>&) = 0; 54 virtual MediaTime duration() = 0; 55 virtual void setDuration(const MediaTime&) = 0; 54 virtual void durationChanged() = 0; 56 55 enum EndOfStreamStatus { EosNoError, EosNetworkError, EosDecodeError }; 57 56 virtual void markEndOfStream(EndOfStreamStatus) = 0; … … 60 59 virtual MediaPlayer::ReadyState readyState() const = 0; 61 60 virtual void setReadyState(MediaPlayer::ReadyState) = 0; 61 62 virtual void waitForSeekCompleted() = 0; 63 virtual void seekCompleted() = 0; 62 64 }; 63 65 -
trunk/Source/WebCore/platform/graphics/MediaSourcePrivateClient.h
r165676 r171033 43 43 virtual double duration() const = 0; 44 44 virtual std::unique_ptr<PlatformTimeRanges> buffered() const = 0; 45 virtual void seekToTime(const MediaTime&) = 0; 45 46 }; 46 47 -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h
r170438 r171033 66 66 67 67 void seekInternal(); 68 void waitForSeekCompleted(); 69 void seekCompleted(); 68 70 void setLoadingProgresssed(bool flag) { m_loadingProgressed = flag; } 69 71 void setHasAvailableVideoFrame(bool flag) { m_hasAvailableVideoFrame = flag; } … … 158 160 void destroyLayer(); 159 161 bool shouldBePlaying() const; 162 void seekTimerFired(Timer<MediaPlayerPrivateMediaSourceAVFObjC>&); 160 163 161 164 // MediaPlayer Factory Methods … … 183 186 MediaPlayer* m_player; 184 187 WeakPtrFactory<MediaPlayerPrivateMediaSourceAVFObjC> m_weakPtrFactory; 185 RefPtr<MediaSourcePrivateClient> m_mediaSource;186 188 RefPtr<MediaSourcePrivateAVFObjC> m_mediaSourcePrivate; 187 189 RetainPtr<AVAsset> m_asset; … … 191 193 RetainPtr<id> m_timeJumpedObserver; 192 194 RetainPtr<id> m_durationObserver; 195 Timer<MediaPlayerPrivateMediaSourceAVFObjC> m_seekTimer; 193 196 MediaPlayer::NetworkState m_networkState; 194 197 MediaPlayer::ReadyState m_readyState; -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm
r170512 r171033 30 30 31 31 #import "CDMSession.h" 32 #import "Logging.h" 32 33 #import "MediaSourcePrivateAVFObjC.h" 33 34 #import "MediaSourcePrivateClient.h" … … 135 136 , m_weakPtrFactory(this) 136 137 , m_synchronizer(adoptNS([[getAVSampleBufferRenderSynchronizerClass() alloc] init])) 138 , m_seekTimer(this, &MediaPlayerPrivateMediaSourceAVFObjC::seekTimerFired) 137 139 , m_networkState(MediaPlayer::Empty) 138 140 , m_readyState(MediaPlayer::HaveNothing) … … 150 152 // an arbitrarily large time value of once an hour: 151 153 __block auto weakThis = createWeakPtr(); 152 m_timeJumpedObserver = [m_synchronizer addPeriodicTimeObserverForInterval:toCMTime(MediaTime::createWithDouble(3600)) queue:dispatch_get_main_queue() usingBlock:^(CMTime){ 154 m_timeJumpedObserver = [m_synchronizer addPeriodicTimeObserverForInterval:toCMTime(MediaTime::createWithDouble(3600)) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) { 155 #if LOG_DISABLED 156 UNUSED_PARAM(time); 157 #endif 153 158 // FIXME: Remove the below once <rdar://problem/15798050> is fixed. 154 159 if (!weakThis) … … 156 161 157 162 if (m_seeking && !m_pendingSeek) { 163 LOG(MediaSource, "MediaPlayerPrivateMediaSourceAVFObjC::m_timeJumpedObserver(%p) - time(%s)", weakThis.get(), toString(toMediaTime(time)).utf8().data()); 158 164 m_seeking = false; 165 159 166 if (shouldBePlaying()) 160 167 [m_synchronizer setRate:m_rate]; 168 if (!seeking()) 169 m_player->timeChanged(); 161 170 } 162 163 m_player->timeChanged();164 171 165 172 if (m_pendingSeek) … … 178 185 if (m_durationObserver) 179 186 [m_synchronizer removeTimeObserver:m_durationObserver.get()]; 187 188 m_seekTimer.stop(); 180 189 } 181 190 … … 287 296 } 288 297 289 void MediaPlayerPrivateMediaSourceAVFObjC::load(const String& url, MediaSourcePrivateClient* source)298 void MediaPlayerPrivateMediaSourceAVFObjC::load(const String& url, MediaSourcePrivateClient* client) 290 299 { 291 300 UNUSED_PARAM(url); 292 301 293 m_mediaSource = source; 294 m_mediaSourcePrivate = MediaSourcePrivateAVFObjC::create(this); 295 296 m_mediaSource->setPrivateAndOpen(*m_mediaSourcePrivate); 302 m_mediaSourcePrivate = MediaSourcePrivateAVFObjC::create(this, client); 297 303 } 298 304 … … 407 413 double MediaPlayerPrivateMediaSourceAVFObjC::durationDouble() const 408 414 { 409 return m_mediaSource ? m_mediaSource->duration() : 0;415 return m_mediaSourcePrivate ? m_mediaSourcePrivate->duration().toDouble() : 0; 410 416 } 411 417 … … 432 438 void MediaPlayerPrivateMediaSourceAVFObjC::seekWithTolerance(double time, double negativeThreshold, double positiveThreshold) 433 439 { 440 LOG(MediaSource, "MediaPlayerPrivateMediaSourceAVFObjC::seekWithTolerance(%p) - time(%s), negativeThreshold(%s), positiveThreshold(%s)", this, toString(time).utf8().data(), toString(negativeThreshold).utf8().data(), toString(positiveThreshold).utf8().data()); 434 441 m_seeking = true; 435 m_seekCompleted = false;436 442 auto weakThis = createWeakPtr(); 437 443 m_pendingSeek = std::make_unique<PendingSeek>(MediaTime::createWithDouble(time), MediaTime::createWithDouble(negativeThreshold), MediaTime::createWithDouble(positiveThreshold)); 438 444 439 callOnMainThread([weakThis] { 440 if (!weakThis) 441 return; 442 weakThis.get()->seekInternal(); 443 }); 445 if (m_seekTimer.isActive()) 446 m_seekTimer.stop(); 447 m_seekTimer.startOneShot(0); 448 } 449 450 void MediaPlayerPrivateMediaSourceAVFObjC::seekTimerFired(Timer<MediaPlayerPrivateMediaSourceAVFObjC>&) 451 { 452 seekInternal(); 444 453 } 445 454 … … 461 470 seekTime = m_mediaSourcePrivate->fastSeekTimeForMediaTime(pendingSeek->targetTime, pendingSeek->positiveThreshold, pendingSeek->negativeThreshold); 462 471 472 LOG(MediaSource, "MediaPlayerPrivateMediaSourceAVFObjC::seekInternal(%p) - seekTime(%s)", this, toString(seekTime).utf8().data()); 473 463 474 [m_synchronizer setRate:0 time:toCMTime(seekTime)]; 464 475 m_mediaSourcePrivate->seekToTime(seekTime); 476 } 477 478 void MediaPlayerPrivateMediaSourceAVFObjC::waitForSeekCompleted() 479 { 480 if (!m_seeking) 481 return; 482 LOG(MediaSource, "MediaPlayerPrivateMediaSourceAVFObjC::waitForSeekCompleted(%p)", this); 483 m_seekCompleted = false; 484 } 485 486 void MediaPlayerPrivateMediaSourceAVFObjC::seekCompleted() 487 { 488 if (m_seekCompleted) 489 return; 490 LOG(MediaSource, "MediaPlayerPrivateMediaSourceAVFObjC::seekCompleted(%p)", this); 491 m_seekCompleted = true; 492 if (!m_seeking) 493 m_player->timeChanged(); 465 494 } 466 495 … … 504 533 std::unique_ptr<PlatformTimeRanges> MediaPlayerPrivateMediaSourceAVFObjC::buffered() const 505 534 { 506 return m_mediaSource ? m_mediaSource->buffered() : PlatformTimeRanges::create();535 return m_mediaSourcePrivate ? m_mediaSourcePrivate->buffered() : PlatformTimeRanges::create(); 507 536 } 508 537 … … 637 666 NSArray* times = @[[NSValue valueWithCMTime:toCMTime(duration)]]; 638 667 m_durationObserver = [m_synchronizer addBoundaryTimeObserverForTimes:times queue:dispatch_get_main_queue() usingBlock:[weakThis] { 639 if (weakThis) 668 if (weakThis) { 640 669 weakThis->pauseInternal(); 670 weakThis->m_player->timeChanged(); 671 } 641 672 }]; 642 673 … … 676 707 677 708 m_readyState = readyState; 678 679 if (!m_seekCompleted && m_readyState >= MediaPlayer::HaveCurrentData) {680 m_seekCompleted = true;681 m_player->timeChanged();682 }683 709 684 710 if (shouldBePlaying()) -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h
r170014 r171033 46 46 class CDMSession; 47 47 class MediaPlayerPrivateMediaSourceAVFObjC; 48 class MediaSourcePrivateClient; 48 49 class SourceBufferPrivateAVFObjC; 49 50 class TimeRanges; … … 51 52 class MediaSourcePrivateAVFObjC final : public MediaSourcePrivate { 52 53 public: 53 static RefPtr<MediaSourcePrivateAVFObjC> create(MediaPlayerPrivateMediaSourceAVFObjC* );54 static RefPtr<MediaSourcePrivateAVFObjC> create(MediaPlayerPrivateMediaSourceAVFObjC*, MediaSourcePrivateClient*); 54 55 virtual ~MediaSourcePrivateAVFObjC(); 55 56 … … 58 59 59 60 virtual AddStatus addSourceBuffer(const ContentType&, RefPtr<SourceBufferPrivate>&) override; 60 virtual MediaTime duration() override; 61 virtual void setDuration(const MediaTime&) override; 61 virtual void durationChanged() override; 62 62 virtual void markEndOfStream(EndOfStreamStatus) override; 63 63 virtual void unmarkEndOfStream() override; 64 64 virtual MediaPlayer::ReadyState readyState() const override; 65 65 virtual void setReadyState(MediaPlayer::ReadyState) override; 66 virtual void waitForSeekCompleted() override; 67 virtual void seekCompleted() override; 68 69 MediaTime duration(); 70 std::unique_ptr<PlatformTimeRanges> buffered(); 66 71 67 72 bool hasAudio() const; 68 73 bool hasVideo() const; 69 74 70 void seekToTime( MediaTime);71 MediaTime fastSeekTimeForMediaTime( MediaTime, MediaTime negativeThreshold, MediaTimepositiveThreshold);75 void seekToTime(const MediaTime&); 76 MediaTime fastSeekTimeForMediaTime(const MediaTime&, const MediaTime& negativeThreshold, const MediaTime& positiveThreshold); 72 77 IntSize naturalSize() const; 73 78 … … 77 82 78 83 private: 79 MediaSourcePrivateAVFObjC(MediaPlayerPrivateMediaSourceAVFObjC* );84 MediaSourcePrivateAVFObjC(MediaPlayerPrivateMediaSourceAVFObjC*, MediaSourcePrivateClient*); 80 85 81 86 void sourceBufferPrivateDidChangeActiveState(SourceBufferPrivateAVFObjC*, bool active); … … 90 95 91 96 MediaPlayerPrivateMediaSourceAVFObjC* m_player; 92 MediaTime m_duration;97 RefPtr<MediaSourcePrivateClient> m_client; 93 98 Vector<RefPtr<SourceBufferPrivateAVFObjC>> m_sourceBuffers; 94 99 Vector<SourceBufferPrivateAVFObjC*> m_activeSourceBuffers; -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm
r170014 r171033 33 33 #import "ExceptionCodePlaceholder.h" 34 34 #import "MediaPlayerPrivateMediaSourceAVFObjC.h" 35 #import "MediaSourcePrivateClient.h" 35 36 #import "SourceBufferPrivateAVFObjC.h" 36 37 #import "SoftLinking.h" … … 44 45 #pragma mark MediaSourcePrivateAVFObjC 45 46 46 RefPtr<MediaSourcePrivateAVFObjC> MediaSourcePrivateAVFObjC::create(MediaPlayerPrivateMediaSourceAVFObjC* parent) 47 { 48 return adoptRef(new MediaSourcePrivateAVFObjC(parent)); 49 } 50 51 MediaSourcePrivateAVFObjC::MediaSourcePrivateAVFObjC(MediaPlayerPrivateMediaSourceAVFObjC* parent) 47 RefPtr<MediaSourcePrivateAVFObjC> MediaSourcePrivateAVFObjC::create(MediaPlayerPrivateMediaSourceAVFObjC* parent, MediaSourcePrivateClient* client) 48 { 49 RefPtr<MediaSourcePrivateAVFObjC> mediaSourcePrivate = adoptRef(new MediaSourcePrivateAVFObjC(parent, client)); 50 client->setPrivateAndOpen(*mediaSourcePrivate); 51 return mediaSourcePrivate; 52 } 53 54 MediaSourcePrivateAVFObjC::MediaSourcePrivateAVFObjC(MediaPlayerPrivateMediaSourceAVFObjC* parent, MediaSourcePrivateClient* client) 52 55 : m_player(parent) 53 , m_ duration(MediaTime::invalidTime())56 , m_client(client) 54 57 , m_isEnded(false) 55 58 { … … 92 95 MediaTime MediaSourcePrivateAVFObjC::duration() 93 96 { 94 return m_duration; 95 } 96 97 void MediaSourcePrivateAVFObjC::setDuration(const MediaTime& duration) 98 { 99 if (duration == m_duration) 100 return; 101 102 m_duration = duration; 97 return MediaTime::createWithDouble(m_client->duration()); 98 } 99 100 std::unique_ptr<PlatformTimeRanges> MediaSourcePrivateAVFObjC::buffered() 101 { 102 return m_client->buffered(); 103 } 104 105 void MediaSourcePrivateAVFObjC::durationChanged() 106 { 103 107 m_player->durationChanged(); 104 108 } … … 125 129 { 126 130 m_player->setReadyState(readyState); 131 } 132 133 void MediaSourcePrivateAVFObjC::waitForSeekCompleted() 134 { 135 m_player->waitForSeekCompleted(); 136 } 137 138 void MediaSourcePrivateAVFObjC::seekCompleted() 139 { 140 m_player->seekCompleted(); 127 141 } 128 142 … … 179 193 } 180 194 181 void MediaSourcePrivateAVFObjC::seekToTime(MediaTime time) 182 { 183 for (auto& buffer : m_activeSourceBuffers) 184 buffer->seekToTime(time); 185 } 186 187 MediaTime MediaSourcePrivateAVFObjC::fastSeekTimeForMediaTime(MediaTime targetTime, MediaTime negativeThreshold, MediaTime positiveThreshold) 195 void MediaSourcePrivateAVFObjC::seekToTime(const MediaTime& time) 196 { 197 m_client->seekToTime(time); 198 } 199 200 MediaTime MediaSourcePrivateAVFObjC::fastSeekTimeForMediaTime(const MediaTime& targetTime, const MediaTime& negativeThreshold, const MediaTime& positiveThreshold) 188 201 { 189 202 MediaTime seekTime = targetTime; -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm
r171017 r171033 123 123 - (void)setShouldProvideMediaData:(BOOL)shouldProvideMediaData forTrackID:(CMPersistentTrackID)trackID; 124 124 - (BOOL)shouldProvideMediaDataForTrackID:(CMPersistentTrackID)trackID; 125 - (void)providePendingMediaData; 125 126 - (void)processContentKeyResponseData:(NSData *)contentKeyResponseData forTrackID:(CMPersistentTrackID)trackID; 126 127 - (void)processContentKeyResponseError:(NSError *)error forTrackID:(CMPersistentTrackID)trackID; … … 683 684 static dispatch_once_t onceToken; 684 685 dispatch_once(&onceToken, ^{ 685 globalQueue = dispatch_queue_create("SourceBufferPrivateAVFObjC data parser queue", DISPATCH_QUEUE_ SERIAL);686 globalQueue = dispatch_queue_create("SourceBufferPrivateAVFObjC data parser queue", DISPATCH_QUEUE_CONCURRENT); 686 687 }); 687 688 return globalQueue; -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaSourceGStreamer.cpp
r169539 r171033 43 43 void MediaSourceGStreamer::open(MediaSourcePrivateClient* mediaSource, WebKitMediaSrc* src) 44 44 { 45 mediaSource->setPrivateAndOpen(adoptRef(*new MediaSourceGStreamer(src))); 45 ASSERT(mediaSource); 46 mediaSource->setPrivateAndOpen(adoptRef(*new MediaSourceGStreamer(mediaSource, src))); 46 47 } 47 48 48 MediaSourceGStreamer::MediaSourceGStreamer( WebKitMediaSrc* src)49 MediaSourceGStreamer::MediaSourceGStreamer(MediaSourcePrivateClient* mediaSource, WebKitMediaSrc* src) 49 50 : m_client(adoptRef(new MediaSourceClientGstreamer(src))) 51 , m_mediaSource(mediaSource) 50 52 , m_readyState(MediaPlayer::HaveNothing) 51 53 { 54 ASSERT(m_client); 52 55 } 53 56 … … 62 65 } 63 66 64 void MediaSourceGStreamer:: setDuration(const MediaTime& duration)67 void MediaSourceGStreamer::durationChanged() 65 68 { 66 ASSERT(m_client); 67 m_duration = duration; 68 m_client->didReceiveDuration(duration.toDouble()); 69 m_client->didReceiveDuration(m_mediaSource->duration()); 69 70 } 70 71 71 72 void MediaSourceGStreamer::markEndOfStream(EndOfStreamStatus) 72 73 { 73 ASSERT(m_client);74 74 m_client->didFinishLoading(0); 75 75 } … … 77 77 void MediaSourceGStreamer::unmarkEndOfStream() 78 78 { 79 ASSERT(m_client);80 79 } 81 80 -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaSourceGStreamer.h
r169537 r171033 43 43 static void open(MediaSourcePrivateClient*, WebKitMediaSrc*); 44 44 ~MediaSourceGStreamer(); 45 AddStatus addSourceBuffer(const ContentType&, RefPtr<SourceBufferPrivate>&);46 MediaTime duration() { return m_duration; }47 void setDuration(const MediaTime&);48 void markEndOfStream(EndOfStreamStatus);49 void unmarkEndOfStream();50 MediaPlayer::ReadyState readyState() const { return m_readyState; }51 void setReadyState(MediaPlayer::ReadyState readyState) { m_readyState = readyState; }52 45 53 46 private: 47 // MediaSourcePrivate 48 virtual AddStatus addSourceBuffer(const ContentType&, RefPtr<SourceBufferPrivate>&) override; 49 virtual void durationChanged() override; 50 virtual void markEndOfStream(EndOfStreamStatus) override; 51 virtual void unmarkEndOfStream() override; 52 virtual MediaPlayer::ReadyState readyState() const override { return m_readyState; } 53 virtual void setReadyState(MediaPlayer::ReadyState readyState) override { m_readyState = readyState; } 54 virtual void waitForSeekCompleted() override { } 55 virtual void seekCompleted() override { } 56 54 57 RefPtr<MediaSourceClientGstreamer> m_client; 55 MediaSource GStreamer(WebKitMediaSrc*);56 Media Time m_duration;58 MediaSourcePrivateClient* m_mediaSource; 59 MediaSourceGStreamer(MediaSourcePrivateClient*, WebKitMediaSrc*); 57 60 MediaPlayer::ReadyState m_readyState; 58 61 }; -
trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.cpp
r169568 r171033 85 85 : m_player(player) 86 86 , m_currentTime(MediaTime::zeroTime()) 87 , m_duration(MediaTime::zeroTime())88 87 , m_readyState(MediaPlayer::HaveNothing) 89 88 , m_networkState(MediaPlayer::Empty) 90 89 , m_playing(false) 90 , m_seekCompleted(true) 91 91 { 92 92 } … … 103 103 void MockMediaPlayerMediaSource::load(const String&, MediaSourcePrivateClient* source) 104 104 { 105 m_mediaSource = source; 106 m_mediaSourcePrivate = MockMediaSourcePrivate::create(this); 107 m_mediaSource->setPrivateAndOpen(*m_mediaSourcePrivate); 105 m_mediaSourcePrivate = MockMediaSourcePrivate::create(this, source); 108 106 } 109 107 … … 144 142 bool MockMediaPlayerMediaSource::seeking() const 145 143 { 144 return !m_seekCompleted; 145 } 146 147 bool MockMediaPlayerMediaSource::paused() const 148 { 149 return !m_playing; 150 } 151 152 MediaPlayer::NetworkState MockMediaPlayerMediaSource::networkState() const 153 { 154 return m_networkState; 155 } 156 157 MediaPlayer::ReadyState MockMediaPlayerMediaSource::readyState() const 158 { 159 return m_readyState; 160 } 161 162 double MockMediaPlayerMediaSource::maxTimeSeekableDouble() const 163 { 164 return m_duration.toDouble(); 165 } 166 167 std::unique_ptr<PlatformTimeRanges> MockMediaPlayerMediaSource::buffered() const 168 { 169 if (m_mediaSourcePrivate) 170 return m_mediaSourcePrivate->buffered(); 171 172 return PlatformTimeRanges::create(); 173 } 174 175 bool MockMediaPlayerMediaSource::didLoadingProgress() const 176 { 146 177 return false; 147 178 } 148 179 149 bool MockMediaPlayerMediaSource::paused() const150 {151 return !m_playing;152 }153 154 MediaPlayer::NetworkState MockMediaPlayerMediaSource::networkState() const155 {156 return m_networkState;157 }158 159 MediaPlayer::ReadyState MockMediaPlayerMediaSource::readyState() const160 {161 return m_readyState;162 }163 164 double MockMediaPlayerMediaSource::maxTimeSeekableDouble() const165 {166 return m_duration.toDouble();167 }168 169 std::unique_ptr<PlatformTimeRanges> MockMediaPlayerMediaSource::buffered() const170 {171 if (m_mediaSource)172 return m_mediaSource->buffered();173 174 return PlatformTimeRanges::create();175 }176 177 bool MockMediaPlayerMediaSource::didLoadingProgress() const178 {179 return false;180 }181 182 180 void MockMediaPlayerMediaSource::setSize(const IntSize&) 183 181 { … … 195 193 double MockMediaPlayerMediaSource::durationDouble() const 196 194 { 197 return m_ duration.toDouble();195 return m_mediaSourcePrivate ? m_mediaSourcePrivate->duration() : 0; 198 196 } 199 197 … … 205 203 } else 206 204 m_currentTime = m_mediaSourcePrivate->seekToTime(MediaTime::createWithDouble(time), MediaTime::createWithDouble(negativeTolerance), MediaTime::createWithDouble(positiveTolerance)); 207 m_player->timeChanged(); 208 209 if (m_playing) 210 callOnMainThread(bind(&MockMediaPlayerMediaSource::advanceCurrentTime, this)); 205 206 if (m_seekCompleted) { 207 m_player->timeChanged(); 208 209 if (m_playing) 210 callOnMainThread(bind(&MockMediaPlayerMediaSource::advanceCurrentTime, this)); 211 } 211 212 } 212 213 213 214 void MockMediaPlayerMediaSource::advanceCurrentTime() 214 215 { 215 if (!m_mediaSource )216 return; 217 218 auto buffered = m_mediaSource ->buffered();216 if (!m_mediaSourcePrivate) 217 return; 218 219 auto buffered = m_mediaSourcePrivate->buffered(); 219 220 size_t pos = buffered->find(m_currentTime); 220 221 if (pos == notFound) … … 253 254 } 254 255 256 void MockMediaPlayerMediaSource::waitForSeekCompleted() 257 { 258 m_seekCompleted = false; 259 } 260 261 void MockMediaPlayerMediaSource::seekCompleted() 262 { 263 if (m_seekCompleted) 264 return; 265 m_seekCompleted = true; 266 267 m_player->timeChanged(); 268 269 if (m_playing) 270 callOnMainThread(bind(&MockMediaPlayerMediaSource::advanceCurrentTime, this)); 271 } 272 255 273 unsigned long MockMediaPlayerMediaSource::totalVideoFrames() 256 274 { -
trunk/Source/WebCore/platform/mock/mediasource/MockMediaPlayerMediaSource.h
r169536 r171033 53 53 void setReadyState(MediaPlayer::ReadyState); 54 54 void setNetworkState(MediaPlayer::NetworkState); 55 void waitForSeekCompleted(); 56 void seekCompleted(); 55 57 56 58 private: … … 84 86 85 87 MediaPlayer* m_player; 86 RefPtr<MediaSourcePrivateClient> m_mediaSource;87 88 RefPtr<MockMediaSourcePrivate> m_mediaSourcePrivate; 88 89 … … 92 93 MediaPlayer::NetworkState m_networkState; 93 94 bool m_playing; 95 bool m_seekCompleted; 94 96 }; 95 97 -
trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.cpp
r169536 r171033 31 31 #include "ContentType.h" 32 32 #include "ExceptionCodePlaceholder.h" 33 #include "MediaSourcePrivateClient.h" 33 34 #include "MockMediaPlayerMediaSource.h" 34 35 #include "MockSourceBufferPrivate.h" … … 36 37 namespace WebCore { 37 38 38 RefPtr<MockMediaSourcePrivate> MockMediaSourcePrivate::create(MockMediaPlayerMediaSource* parent )39 RefPtr<MockMediaSourcePrivate> MockMediaSourcePrivate::create(MockMediaPlayerMediaSource* parent, MediaSourcePrivateClient* client) 39 40 { 40 return adoptRef(new MockMediaSourcePrivate(parent)); 41 RefPtr<MockMediaSourcePrivate> mediaSourcePrivate = adoptRef(new MockMediaSourcePrivate(parent, client)); 42 client->setPrivateAndOpen(*mediaSourcePrivate); 43 return mediaSourcePrivate; 41 44 } 42 45 43 MockMediaSourcePrivate::MockMediaSourcePrivate(MockMediaPlayerMediaSource* parent )46 MockMediaSourcePrivate::MockMediaSourcePrivate(MockMediaPlayerMediaSource* parent, MediaSourcePrivateClient* client) 44 47 : m_player(parent) 45 , m_ duration(MediaTime::invalidTime())48 , m_client(client) 46 49 , m_isEnded(false) 47 50 , m_totalVideoFrames(0) … … 85 88 } 86 89 87 MediaTime MockMediaSourcePrivate::duration()90 double MockMediaSourcePrivate::duration() 88 91 { 89 return m_ duration;92 return m_client->duration(); 90 93 } 91 94 92 void MockMediaSourcePrivate::setDuration(const MediaTime& duration)95 std::unique_ptr<PlatformTimeRanges> MockMediaSourcePrivate::buffered() 93 96 { 94 if (duration == m_duration)95 return; 97 return m_client->buffered(); 98 } 96 99 97 m_duration = duration; 98 m_player->updateDuration(duration); 100 void MockMediaSourcePrivate::durationChanged() 101 { 102 m_player->updateDuration(MediaTime::createWithDouble(duration())); 99 103 } 100 104 … … 119 123 { 120 124 m_player->setReadyState(readyState); 125 } 126 127 void MockMediaSourcePrivate::waitForSeekCompleted() 128 { 129 m_player->waitForSeekCompleted(); 130 } 131 132 void MockMediaSourcePrivate::seekCompleted() 133 { 134 m_player->seekCompleted(); 121 135 } 122 136 -
trunk/Source/WebCore/platform/mock/mediasource/MockMediaSourcePrivate.h
r169536 r171033 40 40 class MockMediaSourcePrivate final : public MediaSourcePrivate { 41 41 public: 42 static RefPtr<MockMediaSourcePrivate> create(MockMediaPlayerMediaSource* );42 static RefPtr<MockMediaSourcePrivate> create(MockMediaPlayerMediaSource*, MediaSourcePrivateClient*); 43 43 virtual ~MockMediaSourcePrivate(); 44 44 … … 47 47 bool hasAudio() const; 48 48 bool hasVideo() const; 49 50 double duration(); 51 std::unique_ptr<PlatformTimeRanges> buffered(); 49 52 50 53 MockMediaPlayerMediaSource* player() const { return m_player; } … … 64 67 65 68 private: 66 MockMediaSourcePrivate(MockMediaPlayerMediaSource* );69 MockMediaSourcePrivate(MockMediaPlayerMediaSource*, MediaSourcePrivateClient*); 67 70 68 71 // MediaSourcePrivate Overrides 69 72 virtual AddStatus addSourceBuffer(const ContentType&, RefPtr<SourceBufferPrivate>&) override; 70 virtual MediaTime duration() override; 71 virtual void setDuration(const MediaTime&) override; 73 virtual void durationChanged() override; 72 74 virtual void markEndOfStream(EndOfStreamStatus) override; 73 75 virtual void unmarkEndOfStream() override; 74 76 virtual MediaPlayer::ReadyState readyState() const override; 75 77 virtual void setReadyState(MediaPlayer::ReadyState) override; 78 virtual void waitForSeekCompleted() override; 79 virtual void seekCompleted() override; 76 80 77 81 void sourceBufferPrivateDidChangeActiveState(MockSourceBufferPrivate*, bool active); … … 81 85 82 86 MockMediaPlayerMediaSource* m_player; 83 MediaTime m_duration;87 RefPtr<MediaSourcePrivateClient> m_client; 84 88 Vector<RefPtr<MockSourceBufferPrivate>> m_sourceBuffers; 85 89 Vector<MockSourceBufferPrivate*> m_activeSourceBuffers;
Note:
See TracChangeset
for help on using the changeset viewer.