133 lines
3.6 KiB
C++
133 lines
3.6 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "gtest/gtest.h"
|
|
#include "mp4parse.h"
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <algorithm>
|
|
#include <vector>
|
|
|
|
static intptr_t error_reader(uint8_t* buffer, uintptr_t size, void* userdata) {
|
|
return -1;
|
|
}
|
|
|
|
struct read_vector {
|
|
explicit read_vector(FILE* file, size_t length);
|
|
explicit read_vector(size_t length);
|
|
|
|
size_t location;
|
|
std::vector<uint8_t> buffer;
|
|
};
|
|
|
|
read_vector::read_vector(FILE* file, size_t length) : location(0) {
|
|
buffer.resize(length);
|
|
size_t read = fread(buffer.data(), sizeof(decltype(buffer)::value_type),
|
|
buffer.size(), file);
|
|
buffer.resize(read);
|
|
}
|
|
|
|
read_vector::read_vector(size_t length) : location(0) {
|
|
buffer.resize(length, 0);
|
|
}
|
|
|
|
static intptr_t vector_reader(uint8_t* buffer, uintptr_t size, void* userdata) {
|
|
if (!buffer || !userdata) {
|
|
return -1;
|
|
}
|
|
|
|
auto source = reinterpret_cast<read_vector*>(userdata);
|
|
if (source->location > source->buffer.size()) {
|
|
return -1;
|
|
}
|
|
uintptr_t available =
|
|
source->buffer.data() ? source->buffer.size() - source->location : 0;
|
|
uintptr_t length = std::min(available, size);
|
|
if (length) {
|
|
memcpy(buffer, source->buffer.data() + source->location, length);
|
|
source->location += length;
|
|
}
|
|
return length;
|
|
}
|
|
|
|
TEST(rust, MP4MetadataEmpty)
|
|
{
|
|
Mp4parseStatus rv;
|
|
Mp4parseIo io;
|
|
Mp4parseParser* parser = nullptr;
|
|
|
|
// Shouldn't be able to read with no context.
|
|
rv = mp4parse_new(nullptr, nullptr);
|
|
EXPECT_EQ(rv, MP4PARSE_STATUS_BAD_ARG);
|
|
|
|
// Shouldn't be able to wrap an Mp4parseIo with null members.
|
|
io = {nullptr, nullptr};
|
|
rv = mp4parse_new(&io, &parser);
|
|
EXPECT_EQ(rv, MP4PARSE_STATUS_BAD_ARG);
|
|
EXPECT_EQ(parser, nullptr);
|
|
|
|
io = {nullptr, &io};
|
|
rv = mp4parse_new(&io, &parser);
|
|
EXPECT_EQ(rv, MP4PARSE_STATUS_BAD_ARG);
|
|
EXPECT_EQ(parser, nullptr);
|
|
|
|
// FIXME: this should probably be accepted.
|
|
io = {error_reader, nullptr};
|
|
rv = mp4parse_new(&io, &parser);
|
|
EXPECT_EQ(rv, MP4PARSE_STATUS_BAD_ARG);
|
|
EXPECT_EQ(parser, nullptr);
|
|
|
|
// Read method errors should propagate.
|
|
io = {error_reader, &io};
|
|
rv = mp4parse_new(&io, &parser);
|
|
ASSERT_EQ(parser, nullptr);
|
|
EXPECT_EQ(rv, MP4PARSE_STATUS_IO);
|
|
|
|
// Short buffers should fail.
|
|
read_vector buf(0);
|
|
io = {vector_reader, &buf};
|
|
rv = mp4parse_new(&io, &parser);
|
|
ASSERT_EQ(parser, nullptr);
|
|
EXPECT_EQ(rv, MP4PARSE_STATUS_MOOV_MISSING);
|
|
|
|
buf.buffer.reserve(4097);
|
|
rv = mp4parse_new(&io, &parser);
|
|
ASSERT_EQ(parser, nullptr);
|
|
EXPECT_EQ(rv, MP4PARSE_STATUS_MOOV_MISSING);
|
|
|
|
// Empty buffers should fail.
|
|
buf.buffer.resize(4097, 0);
|
|
rv = mp4parse_new(&io, &parser);
|
|
ASSERT_EQ(parser, nullptr);
|
|
EXPECT_EQ(rv, MP4PARSE_STATUS_UNSUPPORTED);
|
|
}
|
|
|
|
TEST(rust, MP4Metadata)
|
|
{
|
|
FILE* f = fopen("street.mp4", "rb");
|
|
ASSERT_TRUE(f != nullptr);
|
|
// Read just the moov header to work around the parser
|
|
// treating mid-box eof as an error.
|
|
// read_vector reader = read_vector(f, 1061);
|
|
struct stat s;
|
|
ASSERT_EQ(0, fstat(fileno(f), &s));
|
|
read_vector reader = read_vector(f, s.st_size);
|
|
fclose(f);
|
|
|
|
Mp4parseIo io = {vector_reader, &reader};
|
|
Mp4parseParser* parser = nullptr;
|
|
Mp4parseStatus rv = mp4parse_new(&io, &parser);
|
|
ASSERT_NE(nullptr, parser);
|
|
EXPECT_EQ(MP4PARSE_STATUS_OK, rv);
|
|
|
|
uint32_t tracks = 0;
|
|
rv = mp4parse_get_track_count(parser, &tracks);
|
|
EXPECT_EQ(MP4PARSE_STATUS_OK, rv);
|
|
EXPECT_EQ(2U, tracks);
|
|
|
|
mp4parse_free(parser);
|
|
}
|