1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.mediav2.cts; 18 19 import android.media.MediaCodec; 20 import android.media.MediaFormat; 21 import android.media.MediaMuxer; 22 23 import androidx.test.filters.SmallTest; 24 25 import org.junit.After; 26 import org.junit.Before; 27 import org.junit.Ignore; 28 import org.junit.Rule; 29 import org.junit.Test; 30 import org.junit.experimental.runners.Enclosed; 31 import org.junit.rules.TestName; 32 import org.junit.runner.RunWith; 33 34 import java.io.File; 35 import java.io.FileDescriptor; 36 import java.io.FileInputStream; 37 import java.io.FileOutputStream; 38 import java.io.IOException; 39 import java.nio.ByteBuffer; 40 import java.nio.charset.StandardCharsets; 41 42 import static android.system.Os.pipe; 43 import static org.junit.Assert.assertTrue; 44 import static org.junit.Assert.fail; 45 46 /** 47 * Tests MediaMuxer API that are independent of MediaMuxer.OutputFormat. Constructors, 48 * addTrack, start, writeSampleData, stop, release are independent of OutputFormat selected. 49 * Legality of these APIs are tested in this class. 50 */ 51 @RunWith(Enclosed.class) 52 public class MuxerUnitTest { 53 // duplicate definitions of hide fields of MediaMuxer.OutputFormat. 54 private static final int MUXER_OUTPUT_LAST = MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG; 55 56 @SmallTest 57 public static class TestApi { 58 @Rule 59 public TestName testName = new TestName(); 60 61 @Before prologue()62 public void prologue() throws IOException { 63 mOutMedia = File.createTempFile(testName.getMethodName(), ".out"); 64 mOutLoc = mOutMedia.getAbsolutePath(); 65 } 66 67 @After epilogue()68 public void epilogue() { 69 new File(mOutLoc).delete(); 70 } 71 72 private File mOutMedia; 73 private String mOutLoc; 74 75 // Insert one frame SubRip insertPerFrameSubtitles(MediaMuxer muxer, long presentationTimeUs, int trackID)76 static private void insertPerFrameSubtitles(MediaMuxer muxer, long presentationTimeUs, 77 int trackID) { 78 byte[] greeting = "hello world".getBytes(StandardCharsets.UTF_8); 79 ByteBuffer metaBuff = ByteBuffer.allocate(greeting.length); 80 metaBuff.put(greeting); 81 MediaCodec.BufferInfo metaInfo = new MediaCodec.BufferInfo(); 82 metaInfo.offset = 0; 83 metaInfo.size = greeting.length; 84 metaInfo.presentationTimeUs = presentationTimeUs; 85 metaInfo.flags = 0; 86 muxer.writeSampleData(trackID, metaBuff, metaInfo); 87 } 88 89 @Test testIfNullPathIsRejected()90 public void testIfNullPathIsRejected() { 91 MediaMuxer muxer = null; 92 try { 93 String nullPath = null; 94 muxer = new MediaMuxer(nullPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP); 95 fail("null destination path accepted by constructor"); 96 } catch (IllegalArgumentException e) { 97 // expected 98 } catch (Exception e) { 99 fail(e.getMessage()); 100 } finally { 101 if (null != muxer) muxer.release(); 102 } 103 } 104 105 @Test testIfNullFdIsRejected()106 public void testIfNullFdIsRejected() { 107 MediaMuxer muxer = null; 108 try { 109 FileDescriptor fd = null; 110 muxer = new MediaMuxer(fd, MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP); 111 fail("null fd accepted by constructor"); 112 } catch (IllegalArgumentException e) { 113 // expected 114 } catch (Exception e) { 115 fail(e.getMessage()); 116 } finally { 117 if (null != muxer) muxer.release(); 118 } 119 } 120 121 @Test testIfInvalidFdIsRejected()122 public void testIfInvalidFdIsRejected() { 123 MediaMuxer muxer = null; 124 try { 125 FileDescriptor fd = new FileDescriptor(); 126 muxer = new MediaMuxer(fd, MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP); 127 fail("Invalid fd accepted by constructor"); 128 } catch (IllegalArgumentException e) { 129 // expected 130 } catch (Exception e) { 131 fail(e.getMessage()); 132 } finally { 133 if (null != muxer) muxer.release(); 134 } 135 } 136 137 @Test testIfReadOnlyFdIsRejected()138 public void testIfReadOnlyFdIsRejected() { 139 MediaMuxer muxer = null; 140 try (FileInputStream fInp = new FileInputStream(mOutMedia)) { 141 muxer = new MediaMuxer(fInp.getFD(), MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP); 142 fail("fd with read-only attribute accepted by constructor"); 143 } catch (IOException e) { 144 // expected 145 } catch (Exception e) { 146 fail(e.getMessage()); 147 } finally { 148 if (null != muxer) muxer.release(); 149 } 150 } 151 152 @Test 153 @Ignore("TODO(b/146417874)") testIfWriteOnlyFdIsRejected()154 public void testIfWriteOnlyFdIsRejected() { 155 MediaMuxer muxer = null; 156 try (FileOutputStream fOut = new FileOutputStream(mOutMedia)) { 157 muxer = new MediaMuxer(fOut.getFD(), MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM); 158 fail("fd with write only attribute accepted by constructor"); 159 } catch (Exception e) { 160 // expected 161 } finally { 162 if (null != muxer) muxer.release(); 163 } 164 assertTrue(mOutMedia.delete()); 165 } 166 167 @Test 168 @Ignore("TODO(b/146417874)") testIfNonSeekableFdIsRejected()169 public void testIfNonSeekableFdIsRejected() { 170 MediaMuxer muxer = null; 171 try { 172 FileDescriptor[] fd = pipe(); 173 muxer = new MediaMuxer(fd[1], MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP); 174 fail("pipe, a non-seekable fd accepted by constructor"); 175 } catch (IOException e) { 176 // expected 177 } catch (Exception e) { 178 fail(e.getMessage()); 179 } finally { 180 if (null != muxer) muxer.release(); 181 } 182 } 183 184 @Test testIfInvalidOutputFormatIsRejected()185 public void testIfInvalidOutputFormatIsRejected() { 186 MediaMuxer muxer = null; 187 try { 188 muxer = new MediaMuxer(mOutLoc, MUXER_OUTPUT_LAST + 1); 189 fail("Invalid Media format accepted by constructor"); 190 } catch (IllegalArgumentException e) { 191 // expected 192 } catch (Exception e) { 193 fail(e.getMessage()); 194 } finally { 195 if (null != muxer) muxer.release(); 196 } 197 } 198 199 @Test testIfNullMediaFormatIsRejected()200 public void testIfNullMediaFormatIsRejected() throws IOException { 201 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 202 try { 203 muxer.addTrack(null); 204 fail("null media format accepted by addTrack"); 205 } catch (IllegalArgumentException e) { 206 // expected 207 } finally { 208 muxer.release(); 209 } 210 } 211 212 @Test testIfInvalidMediaFormatIsRejected()213 public void testIfInvalidMediaFormatIsRejected() throws IOException { 214 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 215 try { 216 // Invalid media format - no mime key 217 try { 218 muxer.addTrack(new MediaFormat()); 219 fail("Invalid media format accepted by addTrack"); 220 } catch (IllegalArgumentException e) { 221 // expected 222 } 223 224 // metadata mime format shall start with "application/*" 225 try { 226 MediaFormat format = new MediaFormat(); 227 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_CEA_608); 228 muxer.addTrack(format); 229 fail("Invalid media format accepted by addTrack"); 230 } catch (IllegalArgumentException | IllegalStateException e) { 231 // Ideally check only for IllegalArgumentException. 232 // expected 233 } 234 } finally { 235 muxer.release(); 236 } 237 } 238 239 @Test 240 @Ignore("TODO(b/146923138)") testIfCorruptMediaFormatIsRejected()241 public void testIfCorruptMediaFormatIsRejected() throws IOException { 242 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 243 244 /* TODO: Audio/Video formats, have certain keys required to be set. It is noticed 245 that even when these keys are not set, no exceptions were raised. Do we need to 246 add fixtures for those cases. */ 247 try { 248 MediaFormat format = new MediaFormat(); 249 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_AUDIO_AAC); 250 format.setInteger(MediaFormat.KEY_SAMPLE_RATE, -1); 251 muxer.addTrack(format); 252 muxer.start(); 253 fail("muxer accepts media format with required key-value pairs missing"); 254 } catch (Exception e) { 255 // expected 256 } finally { 257 muxer.release(); 258 } 259 } 260 261 @Test 262 @Ignore("TODO(b/146423844)") testIfAddTrackSucceedsAfterStart()263 public void testIfAddTrackSucceedsAfterStart() throws IOException { 264 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 265 try { 266 MediaFormat format = new MediaFormat(); 267 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 268 muxer.addTrack(format); 269 muxer.start(); 270 muxer.addTrack(format); 271 fail("muxer.addTrack() succeeded after muxer.start()"); 272 } catch (IllegalStateException e) { 273 // expected 274 } catch (Exception e) { 275 fail(e.getMessage()); 276 } finally { 277 muxer.release(); 278 } 279 } 280 281 @Test testIfAddTrackSucceedsAfterWriteSampleData()282 public void testIfAddTrackSucceedsAfterWriteSampleData() throws IOException { 283 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 284 try { 285 MediaFormat format = new MediaFormat(); 286 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 287 int trackID = muxer.addTrack(format); 288 muxer.start(); 289 insertPerFrameSubtitles(muxer, 0, trackID); 290 muxer.addTrack(format); 291 fail("muxer.addTrack() succeeded after muxer.writeSampleData()"); 292 } catch (IllegalStateException e) { 293 // expected 294 } catch (Exception e) { 295 fail(e.getMessage()); 296 } finally { 297 muxer.release(); 298 } 299 } 300 301 @Test testIfAddTrackSucceedsAfterStop()302 public void testIfAddTrackSucceedsAfterStop() throws IOException { 303 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 304 try { 305 MediaFormat format = new MediaFormat(); 306 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 307 int trackID = muxer.addTrack(format); 308 muxer.start(); 309 insertPerFrameSubtitles(muxer, 0, trackID); 310 muxer.stop(); 311 muxer.addTrack(format); 312 fail("muxer.addTrack() succeeded after muxer.stop()"); 313 } catch (IllegalStateException e) { 314 // expected 315 } catch (Exception e) { 316 fail(e.getMessage()); 317 } finally { 318 muxer.release(); 319 } 320 } 321 322 @Test testIfAddTrackSucceedsAfterRelease()323 public void testIfAddTrackSucceedsAfterRelease() throws IOException { 324 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 325 try { 326 MediaFormat format = new MediaFormat(); 327 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 328 muxer.release(); 329 muxer.addTrack(format); 330 fail("muxer.addTrack() succeeded after muxer.release()"); 331 } catch (IllegalStateException e) { 332 // expected 333 } catch (Exception e) { 334 fail(e.getMessage()); 335 } finally { 336 muxer.release(); 337 } 338 } 339 340 @Test testIfMuxerStartsBeforeAddTrack()341 public void testIfMuxerStartsBeforeAddTrack() throws IOException { 342 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 343 MediaFormat format = new MediaFormat(); 344 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 345 346 try { 347 muxer.start(); 348 fail("muxer.start() succeeded before muxer.addTrack()"); 349 } catch (IllegalStateException e) { 350 // expected 351 } catch (Exception e) { 352 fail(e.getMessage()); 353 } finally { 354 muxer.release(); 355 } 356 } 357 358 @Test 359 @Ignore("TODO(b/146423844)") testIdempotentStart()360 public void testIdempotentStart() throws IOException { 361 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 362 MediaFormat format = new MediaFormat(); 363 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 364 365 try { 366 muxer.addTrack(format); 367 muxer.start(); 368 muxer.start(); 369 fail("muxer.start() succeeded after muxer.start()"); 370 } catch (IllegalStateException e) { 371 // expected 372 } catch (Exception e) { 373 fail(e.getMessage()); 374 } finally { 375 muxer.release(); 376 } 377 } 378 379 @Test testIfMuxerStartsAfterWriteSampleData()380 public void testIfMuxerStartsAfterWriteSampleData() throws IOException { 381 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 382 MediaFormat format = new MediaFormat(); 383 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 384 385 try { 386 int trackID = muxer.addTrack(format); 387 muxer.start(); 388 insertPerFrameSubtitles(muxer, 0, trackID); 389 muxer.start(); 390 fail("muxer.start() succeeded after muxer.writeSampleData()"); 391 } catch (IllegalStateException e) { 392 // expected 393 } catch (Exception e) { 394 fail(e.getMessage()); 395 } finally { 396 muxer.release(); 397 } 398 } 399 400 @Test testIfMuxerStartsAfterStop()401 public void testIfMuxerStartsAfterStop() throws IOException { 402 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 403 MediaFormat format = new MediaFormat(); 404 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 405 406 try { 407 int trackID = muxer.addTrack(format); 408 muxer.start(); 409 insertPerFrameSubtitles(muxer, 0, trackID); 410 muxer.stop(); 411 muxer.start(); 412 fail("muxer.start() succeeded after muxer.stop()"); 413 } catch (IllegalStateException e) { 414 // expected 415 } catch (Exception e) { 416 fail(e.getMessage()); 417 } finally { 418 muxer.release(); 419 } 420 } 421 422 @Test testIfMuxerStartsAfterRelease()423 public void testIfMuxerStartsAfterRelease() throws IOException { 424 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 425 426 try { 427 muxer.release(); 428 muxer.start(); 429 fail("muxer.start() succeeded after muxer.release()"); 430 } catch (IllegalStateException e) { 431 // expected 432 } catch (Exception e) { 433 fail(e.getMessage()); 434 } finally { 435 muxer.release(); 436 } 437 } 438 439 @Test testStopOnANonStartedMuxer()440 public void testStopOnANonStartedMuxer() throws IOException { 441 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 442 443 try { 444 muxer.stop(); 445 fail("muxer.stop() succeeded before muxer.start()"); 446 } catch (IllegalStateException e) { 447 // expected 448 } catch (Exception e) { 449 fail(e.getMessage()); 450 } finally { 451 muxer.release(); 452 } 453 } 454 455 @Test testIdempotentStop()456 public void testIdempotentStop() throws IOException { 457 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 458 MediaFormat format = new MediaFormat(); 459 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 460 461 try { 462 int trackID = muxer.addTrack(format); 463 muxer.start(); 464 insertPerFrameSubtitles(muxer, 0, trackID); 465 muxer.stop(); 466 muxer.stop(); 467 fail("muxer.stop() succeeded after muxer.stop()"); 468 } catch (IllegalStateException e) { 469 // expected 470 } catch (Exception e) { 471 fail(e.getMessage()); 472 } finally { 473 muxer.release(); 474 } 475 } 476 477 @Test testStopAfterRelease()478 public void testStopAfterRelease() throws IOException { 479 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 480 try { 481 muxer.release(); 482 muxer.stop(); 483 fail("muxer.stop() succeeded after muxer.release()"); 484 } catch (IllegalStateException e) { 485 // expected 486 } catch (Exception e) { 487 fail(e.getMessage()); 488 } finally { 489 muxer.release(); 490 } 491 } 492 493 @Test 494 @Ignore("TODO(b/146423844)") testSimpleStartStopMuxer()495 public void testSimpleStartStopMuxer() throws IOException { 496 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 497 MediaFormat format = new MediaFormat(); 498 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 499 500 try { 501 muxer.addTrack(format); 502 muxer.start(); 503 muxer.stop(); 504 } catch (Exception e) { 505 fail(e.getMessage()); 506 } finally { 507 muxer.release(); 508 } 509 } 510 511 @Test testIfWriteSampleDataRejectsInvalidTrackIndex()512 public void testIfWriteSampleDataRejectsInvalidTrackIndex() throws IOException { 513 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 514 MediaFormat format = new MediaFormat(); 515 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 516 517 int trackID = muxer.addTrack(format); 518 muxer.start(); 519 insertPerFrameSubtitles(muxer, 22000, trackID); 520 try { 521 insertPerFrameSubtitles(muxer, 0, trackID - 1); 522 fail("muxer.writeSampleData() succeeded with bad argument, trackIndex"); 523 } catch (IllegalArgumentException e) { 524 // expected 525 } finally { 526 muxer.release(); 527 } 528 } 529 530 @Test testIfWriteSampleDataRejectsNullByteBuffer()531 public void testIfWriteSampleDataRejectsNullByteBuffer() throws IOException { 532 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 533 MediaFormat format = new MediaFormat(); 534 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 535 536 int trackID = muxer.addTrack(format); 537 muxer.start(); 538 insertPerFrameSubtitles(muxer, 22000, trackID); 539 540 MediaCodec.BufferInfo metaInfo = new MediaCodec.BufferInfo(); 541 metaInfo.offset = 0; 542 metaInfo.size = 24; 543 metaInfo.presentationTimeUs = 0; 544 metaInfo.flags = 0; 545 try { 546 muxer.writeSampleData(trackID, null, metaInfo); 547 fail("muxer.writeSampleData() succeeded with bad argument, byteBuffer = null"); 548 } catch (IllegalArgumentException e) { 549 // expected 550 } finally { 551 muxer.release(); 552 } 553 } 554 555 @Test testIfWriteSampleDataRejectsNullBuffInfo()556 public void testIfWriteSampleDataRejectsNullBuffInfo() throws IOException { 557 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 558 MediaFormat format = new MediaFormat(); 559 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 560 561 int trackID = muxer.addTrack(format); 562 muxer.start(); 563 insertPerFrameSubtitles(muxer, 22000, trackID); 564 565 byte[] greeting = "hello world".getBytes(StandardCharsets.UTF_8); 566 ByteBuffer metaBuff = ByteBuffer.allocate(greeting.length); 567 metaBuff.put(greeting); 568 569 try { 570 muxer.writeSampleData(trackID, metaBuff, null); 571 fail("muxer.writeSampleData() succeeded with bad argument, byteBuffer = null"); 572 } catch (IllegalArgumentException e) { 573 // expected 574 } finally { 575 muxer.release(); 576 } 577 } 578 579 @Test testIfWriteSampleDataRejectsInvalidBuffInfo()580 public void testIfWriteSampleDataRejectsInvalidBuffInfo() throws IOException { 581 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 582 MediaFormat format = new MediaFormat(); 583 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 584 585 int trackID = muxer.addTrack(format); 586 muxer.start(); 587 insertPerFrameSubtitles(muxer, 22000, trackID); 588 589 byte[] greeting = "hello world".getBytes(StandardCharsets.UTF_8); 590 ByteBuffer metaBuff = ByteBuffer.allocate(greeting.length); 591 metaBuff.put(greeting); 592 593 MediaCodec.BufferInfo metaInfo = new MediaCodec.BufferInfo(); 594 595 try { 596 // invalid metaData : buffer offset < 0 597 try { 598 metaInfo.offset = -1; 599 metaInfo.size = greeting.length; 600 metaInfo.presentationTimeUs = 0; 601 metaInfo.flags = 0; 602 muxer.writeSampleData(trackID, metaBuff, metaInfo); 603 fail("muxer.writeSampleData() succeeded with bad argument, bufInfo.offset < 0"); 604 } catch (IllegalArgumentException e) { 605 // expected 606 } 607 608 // invalid metaData : buffer size < 0 609 try { 610 metaInfo.offset = 0; 611 metaInfo.size = -1; 612 metaInfo.presentationTimeUs = 0; 613 metaInfo.flags = 0; 614 muxer.writeSampleData(trackID, metaBuff, metaInfo); 615 fail("muxer.writeSampleData() succeeded with bad argument, buffInfo.size < 0"); 616 } catch (IllegalArgumentException e) { 617 // expected 618 } 619 620 // invalid metaData : buffer size > capacity 621 try { 622 metaInfo.offset = 0; 623 metaInfo.size = greeting.length * 2; 624 metaInfo.presentationTimeUs = 0; 625 metaInfo.flags = 0; 626 muxer.writeSampleData(trackID, metaBuff, metaInfo); 627 fail("muxer.writeSampleData() succeeded with bad argument, buffInfo.size > " + 628 "byteBuffer.capacity()"); 629 } catch (IllegalArgumentException e) { 630 // expected 631 } 632 633 // invalid metaData : buffer offset + size > capacity 634 try { 635 metaInfo.offset = 1; 636 metaInfo.size = greeting.length; 637 metaInfo.presentationTimeUs = 0; 638 metaInfo.flags = 0; 639 muxer.writeSampleData(trackID, metaBuff, metaInfo); 640 fail("muxer.writeSampleData() succeeded with bad argument, bufferInfo.offset " + 641 "+ bufferInfo.size > byteBuffer.capacity()"); 642 } catch (IllegalArgumentException e) { 643 // expected 644 } 645 } finally { 646 muxer.release(); 647 } 648 } 649 650 @Test 651 @Ignore("TODO(b/147128377)") testIfWriteSampleDataRejectsInvalidPts()652 public void testIfWriteSampleDataRejectsInvalidPts() throws IOException { 653 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 654 MediaFormat format = new MediaFormat(); 655 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 656 657 int trackID = muxer.addTrack(format); 658 muxer.start(); 659 insertPerFrameSubtitles(muxer, 22000, trackID); 660 try { 661 insertPerFrameSubtitles(muxer, -33000, trackID); 662 fail("muxer.writeSampleData() succeeded with bad argument, presentationTime"); 663 } catch (IllegalArgumentException e) { 664 // expected 665 } finally { 666 muxer.release(); 667 } 668 } 669 670 @Test testIfWriteSampleDataSucceedsBeforeStart()671 public void testIfWriteSampleDataSucceedsBeforeStart() throws IOException { 672 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 673 MediaFormat format = new MediaFormat(); 674 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 675 676 try { 677 int trackID = muxer.addTrack(format); 678 insertPerFrameSubtitles(muxer, 0, trackID); 679 fail("muxer.WriteSampleData() succeeds before muxer.start()"); 680 } catch (IllegalStateException e) { 681 // expected 682 } catch (Exception e) { 683 fail(e.getMessage()); 684 } finally { 685 muxer.release(); 686 } 687 } 688 689 @Test testIfWriteSampleDataSucceedsAfterStop()690 public void testIfWriteSampleDataSucceedsAfterStop() throws IOException { 691 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 692 MediaFormat format = new MediaFormat(); 693 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 694 695 try { 696 int trackID = muxer.addTrack(format); 697 muxer.start(); 698 insertPerFrameSubtitles(muxer, 0, trackID); 699 muxer.stop(); 700 insertPerFrameSubtitles(muxer, 0, trackID); 701 fail("muxer.WriteSampleData() succeeds after muxer.stop()"); 702 } catch (IllegalStateException e) { 703 // expected 704 } catch (Exception e) { 705 fail(e.getMessage()); 706 } finally { 707 muxer.release(); 708 } 709 } 710 711 @Test testIfWriteSampleDataSucceedsAfterRelease()712 public void testIfWriteSampleDataSucceedsAfterRelease() throws IOException { 713 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 714 MediaFormat format = new MediaFormat(); 715 format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_TEXT_SUBRIP); 716 717 try { 718 int trackID = muxer.addTrack(format); 719 muxer.start(); 720 insertPerFrameSubtitles(muxer, 0, trackID); 721 muxer.release(); 722 insertPerFrameSubtitles(muxer, 0, trackID); 723 fail("muxer.WriteSampleData() succeeds after muxer.release()"); 724 } catch (IllegalStateException e) { 725 // expected 726 } catch (Exception e) { 727 fail(e.getMessage()); 728 } finally { 729 muxer.release(); 730 } 731 } 732 733 @Test testIdempotentRelease()734 public void testIdempotentRelease() throws IOException { 735 MediaMuxer muxer = new MediaMuxer(mOutLoc, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 736 try { 737 muxer.release(); 738 muxer.release(); 739 } catch (Exception e) { 740 fail(e.getMessage()); 741 } 742 } 743 } 744 745 @SmallTest 746 public static class TestApiNative { 747 @Rule 748 public TestName testName = new TestName(); 749 750 static { 751 System.loadLibrary("ctsmediav2muxer_jni"); 752 } 753 754 @Before prologue()755 public void prologue() throws IOException { 756 File mOutMedia = File.createTempFile(testName.getMethodName(), ".out"); 757 mOutLoc = mOutMedia.getAbsolutePath(); 758 } 759 760 @After epilogue()761 public void epilogue() { 762 new File(mOutLoc).delete(); 763 } 764 765 private String mOutLoc; 766 nativeTestIfInvalidFdIsRejected()767 private native boolean nativeTestIfInvalidFdIsRejected(); nativeTestIfReadOnlyFdIsRejected(String outPath)768 private native boolean nativeTestIfReadOnlyFdIsRejected(String outPath); nativeTestIfWriteOnlyFdIsRejected(String outPath)769 private native boolean nativeTestIfWriteOnlyFdIsRejected(String outPath); nativeTestIfNonSeekableFdIsRejected(String outPath)770 private native boolean nativeTestIfNonSeekableFdIsRejected(String outPath); nativeTestIfInvalidOutputFormatIsRejected(String outPath)771 private native boolean nativeTestIfInvalidOutputFormatIsRejected(String outPath); 772 nativeTestIfInvalidMediaFormatIsRejected(String outPath)773 private native boolean nativeTestIfInvalidMediaFormatIsRejected(String outPath); nativeTestIfCorruptMediaFormatIsRejected(String outPath)774 private native boolean nativeTestIfCorruptMediaFormatIsRejected(String outPath); nativeTestIfAddTrackSucceedsAfterStart(String outPath)775 private native boolean nativeTestIfAddTrackSucceedsAfterStart(String outPath); nativeTestIfAddTrackSucceedsAfterWriteSampleData(String outPath)776 private native boolean nativeTestIfAddTrackSucceedsAfterWriteSampleData(String outPath); nativeTestIfAddTrackSucceedsAfterStop(String outPath)777 private native boolean nativeTestIfAddTrackSucceedsAfterStop(String outPath); 778 nativeTestIfMuxerStartsBeforeAddTrack(String outPath)779 private native boolean nativeTestIfMuxerStartsBeforeAddTrack(String outPath); nativeTestIdempotentStart(String outPath)780 private native boolean nativeTestIdempotentStart(String outPath); nativeTestIfMuxerStartsAfterWriteSampleData(String outPath)781 private native boolean nativeTestIfMuxerStartsAfterWriteSampleData(String outPath); nativeTestIfMuxerStartsAfterStop(String outPath)782 private native boolean nativeTestIfMuxerStartsAfterStop(String outPath); 783 nativeTestStopOnANonStartedMuxer(String outPath)784 private native boolean nativeTestStopOnANonStartedMuxer(String outPath); nativeTestIdempotentStop(String outPath)785 private native boolean nativeTestIdempotentStop(String outPath); nativeTestSimpleStartStop(String outPath)786 private native boolean nativeTestSimpleStartStop(String outPath); 787 nativeTestIfWriteSampleDataRejectsInvalidTrackIndex(String outPath)788 private native boolean nativeTestIfWriteSampleDataRejectsInvalidTrackIndex(String outPath); nativeTestIfWriteSampleDataRejectsInvalidPts(String outPath)789 private native boolean nativeTestIfWriteSampleDataRejectsInvalidPts(String outPath); nativeTestIfWriteSampleDataSucceedsBeforeStart(String outPath)790 private native boolean nativeTestIfWriteSampleDataSucceedsBeforeStart(String outPath); nativeTestIfWriteSampleDataSucceedsAfterStop(String outPath)791 private native boolean nativeTestIfWriteSampleDataSucceedsAfterStop(String outPath); 792 793 @Test 794 @Ignore("TODO(b/146417874)") testIfInvalidFdIsRejected()795 public void testIfInvalidFdIsRejected() { 796 assertTrue(nativeTestIfInvalidFdIsRejected()); 797 } 798 799 @Test 800 @Ignore("TODO(b/146417874)") testIfReadOnlyFdIsRejected()801 public void testIfReadOnlyFdIsRejected() { 802 assertTrue(nativeTestIfReadOnlyFdIsRejected(mOutLoc)); 803 } 804 805 @Test 806 @Ignore("TODO(b/146417874)") testIfWriteOnlyFdIsRejected()807 public void testIfWriteOnlyFdIsRejected() { 808 assertTrue(nativeTestIfWriteOnlyFdIsRejected(mOutLoc)); 809 } 810 811 @Test 812 @Ignore("TODO(b/146417874)") testIfNonSeekableFdIsRejected()813 public void testIfNonSeekableFdIsRejected() { 814 assertTrue(nativeTestIfNonSeekableFdIsRejected(mOutLoc)); 815 } 816 817 @Test 818 @Ignore("TODO(b/146417874)") testIfInvalidOutputFormatIsRejected()819 public void testIfInvalidOutputFormatIsRejected() { 820 assertTrue(nativeTestIfInvalidOutputFormatIsRejected(mOutLoc)); 821 } 822 823 @Test testIfInvalidMediaFormatIsRejected()824 public void testIfInvalidMediaFormatIsRejected() { 825 assertTrue(nativeTestIfInvalidMediaFormatIsRejected(mOutLoc)); 826 } 827 828 @Test 829 @Ignore("TODO(b/146923138)") testIfCorruptMediaFormatIsRejected()830 public void testIfCorruptMediaFormatIsRejected() { 831 assertTrue(nativeTestIfCorruptMediaFormatIsRejected(mOutLoc)); 832 } 833 834 @Test testIfAddTrackSucceedsAfterStart()835 public void testIfAddTrackSucceedsAfterStart() { 836 assertTrue(nativeTestIfAddTrackSucceedsAfterStart(mOutLoc)); 837 } 838 839 @Test testIfAddTrackSucceedsAfterWriteSampleData()840 public void testIfAddTrackSucceedsAfterWriteSampleData() { 841 assertTrue(nativeTestIfAddTrackSucceedsAfterWriteSampleData(mOutLoc)); 842 } 843 844 @Test testIfAddTrackSucceedsAfterStop()845 public void testIfAddTrackSucceedsAfterStop() { 846 assertTrue(nativeTestIfAddTrackSucceedsAfterStop(mOutLoc)); 847 } 848 849 @Test testIfMuxerStartsBeforeAddTrack()850 public void testIfMuxerStartsBeforeAddTrack() { 851 assertTrue(nativeTestIfMuxerStartsBeforeAddTrack(mOutLoc)); 852 } 853 854 @Test testIdempotentStart()855 public void testIdempotentStart() { 856 assertTrue(nativeTestIdempotentStart(mOutLoc)); 857 } 858 859 @Test testIfMuxerStartsAfterWriteSampleData()860 public void testIfMuxerStartsAfterWriteSampleData() { 861 assertTrue(nativeTestIfMuxerStartsAfterWriteSampleData(mOutLoc)); 862 } 863 864 @Test testIfMuxerStartsAfterStop()865 public void testIfMuxerStartsAfterStop() { 866 assertTrue(nativeTestIfMuxerStartsAfterStop(mOutLoc)); 867 } 868 869 @Test testStopOnANonStartedMuxer()870 public void testStopOnANonStartedMuxer() { 871 assertTrue(nativeTestStopOnANonStartedMuxer(mOutLoc)); 872 } 873 874 @Test testIdempotentStop()875 public void testIdempotentStop() { 876 assertTrue(nativeTestIdempotentStop(mOutLoc)); 877 } 878 879 @Test 880 @Ignore("TODO(b/146423844)") testSimpleStartStopMuxer()881 public void testSimpleStartStopMuxer() { 882 assertTrue(nativeTestSimpleStartStop(mOutLoc)); 883 } 884 885 @Test testIfWriteSampleDataRejectsInvalidTrackIndex()886 public void testIfWriteSampleDataRejectsInvalidTrackIndex() { 887 assertTrue(nativeTestIfWriteSampleDataRejectsInvalidTrackIndex(mOutLoc)); 888 } 889 890 @Test 891 @Ignore("TODO(b/147128377)") testIfWriteSampleDataRejectsInvalidPts()892 public void testIfWriteSampleDataRejectsInvalidPts() { 893 assertTrue(nativeTestIfWriteSampleDataRejectsInvalidPts(mOutLoc)); 894 } 895 896 @Test testIfWriteSampleDataSucceedsBeforeStart()897 public void testIfWriteSampleDataSucceedsBeforeStart() { 898 assertTrue(nativeTestIfWriteSampleDataSucceedsBeforeStart(mOutLoc)); 899 } 900 901 @Test testIfWriteSampleDataSucceedsAfterStop()902 public void testIfWriteSampleDataSucceedsAfterStop() { 903 assertTrue(nativeTestIfWriteSampleDataSucceedsAfterStop(mOutLoc)); 904 } 905 } 906 } 907