TestMP4.cpp (3726B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include <stdint.h> 7 #include <stdio.h> 8 #include <string.h> 9 10 #include <algorithm> 11 #include <vector> 12 13 #include "gtest/gtest.h" 14 #include "mp4parse.h" 15 16 static intptr_t error_reader(uint8_t* buffer, uintptr_t size, void* userdata) { 17 return -1; 18 } 19 20 struct read_vector { 21 explicit read_vector(FILE* file, size_t length); 22 explicit read_vector(size_t length); 23 24 size_t location; 25 std::vector<uint8_t> buffer; 26 }; 27 28 read_vector::read_vector(FILE* file, size_t length) : location(0) { 29 buffer.resize(length); 30 size_t read = fread(buffer.data(), sizeof(decltype(buffer)::value_type), 31 buffer.size(), file); 32 buffer.resize(read); 33 } 34 35 read_vector::read_vector(size_t length) : location(0) { 36 buffer.resize(length, 0); 37 } 38 39 static intptr_t vector_reader(uint8_t* buffer, uintptr_t size, void* userdata) { 40 if (!buffer || !userdata) { 41 return -1; 42 } 43 44 auto source = reinterpret_cast<read_vector*>(userdata); 45 if (source->location > source->buffer.size()) { 46 return -1; 47 } 48 uintptr_t available = 49 source->buffer.data() ? source->buffer.size() - source->location : 0; 50 uintptr_t length = std::min(available, size); 51 if (length) { 52 memcpy(buffer, source->buffer.data() + source->location, length); 53 source->location += length; 54 } 55 return length; 56 } 57 58 TEST(rust, MP4MetadataEmpty) 59 { 60 Mp4parseStatus rv; 61 Mp4parseIo io; 62 Mp4parseParser* parser = nullptr; 63 64 // Shouldn't be able to read with no context. 65 rv = mp4parse_new(nullptr, nullptr); 66 EXPECT_EQ(rv, MP4PARSE_STATUS_BAD_ARG); 67 68 // Shouldn't be able to wrap an Mp4parseIo with null members. 69 io = {nullptr, nullptr}; 70 rv = mp4parse_new(&io, &parser); 71 EXPECT_EQ(rv, MP4PARSE_STATUS_BAD_ARG); 72 EXPECT_EQ(parser, nullptr); 73 74 io = {nullptr, &io}; 75 rv = mp4parse_new(&io, &parser); 76 EXPECT_EQ(rv, MP4PARSE_STATUS_BAD_ARG); 77 EXPECT_EQ(parser, nullptr); 78 79 // FIXME: this should probably be accepted. 80 io = {error_reader, nullptr}; 81 rv = mp4parse_new(&io, &parser); 82 EXPECT_EQ(rv, MP4PARSE_STATUS_BAD_ARG); 83 EXPECT_EQ(parser, nullptr); 84 85 // Read method errors should propagate. 86 io = {error_reader, &io}; 87 rv = mp4parse_new(&io, &parser); 88 ASSERT_EQ(parser, nullptr); 89 EXPECT_EQ(rv, MP4PARSE_STATUS_IO); 90 91 // Short buffers should fail. 92 read_vector buf(0); 93 io = {vector_reader, &buf}; 94 rv = mp4parse_new(&io, &parser); 95 ASSERT_EQ(parser, nullptr); 96 EXPECT_EQ(rv, MP4PARSE_STATUS_MOOV_MISSING); 97 98 buf.buffer.reserve(4097); 99 rv = mp4parse_new(&io, &parser); 100 ASSERT_EQ(parser, nullptr); 101 EXPECT_EQ(rv, MP4PARSE_STATUS_MOOV_MISSING); 102 103 // Empty buffers should fail. 104 buf.buffer.resize(4097, 0); 105 rv = mp4parse_new(&io, &parser); 106 ASSERT_EQ(parser, nullptr); 107 EXPECT_EQ(rv, MP4PARSE_STATUS_UNSUPPORTED); 108 } 109 110 TEST(rust, MP4Metadata) 111 { 112 FILE* f = fopen("street.mp4", "rb"); 113 ASSERT_TRUE(f != nullptr); 114 // Read just the moov header to work around the parser 115 // treating mid-box eof as an error. 116 // read_vector reader = read_vector(f, 1061); 117 struct stat s; 118 ASSERT_EQ(0, fstat(fileno(f), &s)); 119 read_vector reader = read_vector(f, s.st_size); 120 fclose(f); 121 122 Mp4parseIo io = {vector_reader, &reader}; 123 Mp4parseParser* parser = nullptr; 124 Mp4parseStatus rv = mp4parse_new(&io, &parser); 125 ASSERT_NE(nullptr, parser); 126 EXPECT_EQ(MP4PARSE_STATUS_OK, rv); 127 128 uint32_t tracks = 0; 129 rv = mp4parse_get_track_count(parser, &tracks); 130 EXPECT_EQ(MP4PARSE_STATUS_OK, rv); 131 EXPECT_EQ(2U, tracks); 132 133 mp4parse_free(parser); 134 }