blob: e0378c5d5d451c619fef08af769ed320fbadecb7 [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.
*/
#pragma once
#include <thread>
#include <mutex>
#include <memory>
#include <vector>
#include <list>
#include "frame_queue.h"
#include "common/ivfdec.h"
#include "common/webmdec.h"
#include "common/obudec.h"
#include "common/mp4parser.h"
#include "mkvparser/mkvparser.h"
#include "mkvparser/mkvreader.h"
#include "log.h"
class StreamReader;
class ReaderBuffer {
public:
ReaderBuffer(StreamReader* releaser) : buffer_(0), size_(0), releaser_(releaser) {}
~ReaderBuffer() {
XB_LOGD << "~ReaderBuffer";
delete[] buffer_;
}
int Put(const uint8_t* src, uint32_t size, int last = 0) {
if (src && size) {
if (size > capacity_) {
XB_LOGD << "ReaderBuffer::Put " << size;
delete[] buffer_;
buffer_ = new (std::nothrow) uint8_t[size];
if (!buffer_) return -1;
capacity_ = size;
}
memcpy(buffer_, src, size);
size_ = size;
} else {
delete[] buffer_; // eof case
buffer_ = 0;
size_ = 0;
capacity_ = 0;
}
isFinal_ = last;
return 0;
}
uint8_t* Data() { return buffer_; }
uint32_t Size() { return size_; }
int IsFinal() const { return isFinal_; }
private:
uint8_t* buffer_ = 0;
uint32_t size_ = 0;
uint32_t capacity_ = 0;
uint32_t isFinal_ = 0;
StreamReader* releaser_;
friend class ReadBufferWrapper;
};
typedef std::shared_ptr<ReaderBuffer> reader_buffer_ptr;
class ReadBufferWrapper {
public:
ReadBufferWrapper(reader_buffer_ptr buffer = reader_buffer_ptr(0)) : buffer_(buffer) {}
~ReadBufferWrapper();
ReadBufferWrapper& operator=(reader_buffer_ptr other) {
InternalRelease();
buffer_ = other;
return *this;
}
void Reset() {
InternalRelease();
buffer_ = 0;
}
ReaderBuffer* operator*() { return buffer_.get(); }
operator bool() { return buffer_ != 0; }
ReaderBuffer* operator->() { return buffer_.get(); }
private:
void InternalRelease();
private:
reader_buffer_ptr buffer_;
};
enum StreamReaderMode { srmodeAsync = 0, srmodeSync = 1 };
class StreamReader {
public:
StreamReader(uint32_t mode, uint32_t buffers_num = 20);
~StreamReader() {
Stop();
if (aom_input_ctx_.file) fclose(aom_input_ctx_.file);
if (mp4_context_) destroy_mp4_ctx(mp4_context_);
if (aom_input_ctx_.file_type == FILE_TYPE_IVF)
ivf_free_buffer(&buf_);
else if (aom_input_ctx_.file_type == FILE_TYPE_WEBM)
webm_free(&webm_ctx_);
else if (aom_input_ctx_.file_type == FILE_TYPE_OBU)
obudec_free(&obu_ctx_);
}
int Start(std::string& source_path);
void Stop() {
if (!stop_) {
stop_ = 1;
if (mode_ == srmodeAsync) {
reader_queue_.Push(0);
reading_thread_.join();
}
}
}
reader_buffer_ptr GetData();
void ReleaseData(reader_buffer_ptr data);
size_t GetCount();
double FrameRate() {
if (aom_input_ctx_.framerate.denominator)
return (double)aom_input_ctx_.framerate.numerator / (double)aom_input_ctx_.framerate.denominator;
else
return 30.0;
}
private:
int readFrame(uint8_t** buf, size_t* bytes_in_buffer);
static void ThreadFunc(StreamReader* ptr) { ptr->ReadLoop(); }
int ReadLoop();
std::string sourec_file_;
AvxInputContext aom_input_ctx_ = {};
WebmInputContext webm_ctx_ = {};
ObuDecInputContext obu_ctx_ = {};
mp4context* mp4_context_ = 0;
volatile int stop_ = 1;
volatile int started_ = 0;
std::thread reading_thread_;
std::mutex cs_;
myqueue<reader_buffer_ptr> reader_queue_;
myqueue<reader_buffer_ptr> ready_queue_;
int eof_ = 0;
size_t input_buffer_capacity_ = 0;
uint8_t* buf_ = 0;
uint32_t mode_ = 0;
friend class ReaderBuffer;
};