blob: 3ccc647266073e59dfb3af64f67f83aa2e78b3ed [file] [log] [blame]
/*
* Copyright 2020 Google LLC
*
*/
/*
* Copyright (c) 2020, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "stream_reader.h"
#include "log.h"
void ReadBufferWrapper::InternalRelease() {
if (buffer_) buffer_->releaser_->ReleaseData(buffer_);
buffer_.reset();
}
ReadBufferWrapper::~ReadBufferWrapper() { InternalRelease(); }
void StreamReader::ReleaseData(reader_buffer_ptr data) {
if (data) reader_queue_.Push(data);
}
int StreamReader::readFrame(uint8_t **buf, size_t *bytes_in_buffer) {
switch (aom_input_ctx_.file_type) {
case FILE_TYPE_WEBM:
return webm_read_frame(&webm_ctx_, buf, bytes_in_buffer, &input_buffer_capacity_);
case FILE_TYPE_IVF:
return ivf_read_frame(aom_input_ctx_.file, buf, bytes_in_buffer, &input_buffer_capacity_, NULL);
case FILE_TYPE_OBU:
return obudec_read_temporal_unit(&obu_ctx_, buf, bytes_in_buffer, &input_buffer_capacity_);
case FILE_TYPE_MP4:
return mp4_read_frame(mp4_context_, buf, bytes_in_buffer, &input_buffer_capacity_);
default:
return 1;
}
}
StreamReader::StreamReader(uint32_t mode, uint32_t buffers_num)
: reader_queue_(buffers_num), ready_queue_(buffers_num + 1), mode_(mode) {
for (uint32_t i = 0; i < buffers_num; i++) {
reader_queue_.Push(reader_buffer_ptr(new ReaderBuffer(this)));
}
}
int StreamReader::Start(std::string &source_path) {
sourec_file_ = source_path;
aom_input_ctx_.filename = sourec_file_.c_str();
aom_input_ctx_.file = fopen(aom_input_ctx_.filename, "rb");
obu_ctx_.avx_ctx = &aom_input_ctx_;
mp4_context_ = create_mp4_ctx();
mp4_context_->file = aom_input_ctx_.file;
if (!aom_input_ctx_.file) return -1;
if (file_is_ivf(&aom_input_ctx_))
aom_input_ctx_.file_type = FILE_TYPE_IVF;
else if (file_is_webm(&webm_ctx_, &aom_input_ctx_)) {
aom_input_ctx_.file_type = FILE_TYPE_WEBM;
if (webm_guess_framerate(&webm_ctx_, &aom_input_ctx_)) {
XB_LOGE << "Failed to guess framerate -- error parsing. webm file?";
fclose(aom_input_ctx_.file);
aom_input_ctx_.file = 0;
return -1;
}
} else if (file_is_obu(&obu_ctx_))
aom_input_ctx_.file_type = FILE_TYPE_OBU;
else if (file_is_mp4(mp4_context_, &aom_input_ctx_))
aom_input_ctx_.file_type = FILE_TYPE_MP4;
else {
XB_LOGE << "Unsupported input file type";
fclose(aom_input_ctx_.file);
aom_input_ctx_.file = 0;
return -1;
}
if (mode_ == srmodeAsync) {
stop_ = 0;
eof_ = 0;
reading_thread_ = std::thread(ThreadFunc, this);
}
return 0;
}
int StreamReader::ReadLoop() {
started_ = 1;
while (!stop_) {
size_t buf_size = 0;
reader_buffer_ptr buffer = reader_queue_.Pull();
if (!buffer || readFrame(&buf_, &buf_size)) {
break;
} else {
int ret = buffer->Put(buf_, (uint32_t)buf_size);
if (ret) {
XB_LOGE << "Out of memory while allocating " << buf_size << " bytes";
ready_queue_.Push(0);
return 1;
}
ready_queue_.Push(buffer);
}
}
ready_queue_.Push(0);
if (aom_input_ctx_.file) {
fclose(aom_input_ctx_.file);
aom_input_ctx_.file = 0;
}
return 0;
}
reader_buffer_ptr StreamReader::GetData() {
if (mode_ == srmodeAsync) {
reader_buffer_ptr buffer = ready_queue_.Pull();
if (!buffer) {
return 0;
} else
return buffer;
} else {
size_t buf_size = 0;
reader_buffer_ptr buffer(reader_queue_.Pull());
if (!buffer || readFrame(&buf_, &buf_size)) {
if (aom_input_ctx_.file) {
fclose(aom_input_ctx_.file);
aom_input_ctx_.file = 0;
}
return 0;
} else {
int ret = buffer->Put(buf_, (uint32_t)buf_size);
if (ret) {
XB_LOGE << "Out of memory";
return 0;
}
}
return buffer;
}
}
size_t StreamReader::GetCount() { return ready_queue_.Size(); }