Commit df4f75b9 authored by NzSN's avatar NzSN

update

parent 4f7546b6
......@@ -30,6 +30,14 @@ bool InOutCtx::isReady() noexcept {
return fmt.get() != nullptr;
}
void InOutCtx::closeCustomIO() {
AVFormatContext *fmtCtx = fmt.get();
if (customProto.get()) {
customProto->close();
}
}
///////////////////////////////////////////////////////////////////////////////
......@@ -37,8 +45,14 @@ bool InOutCtx::isReady() noexcept {
///////////////////////////////////////////////////////////////////////////////
void InCtx::readFrame(AVPacket *packet) {
if (av_read_frame(fmt.get(), packet) < 0)
throw END_OF_FILE();
int err = av_read_frame(fmt.get(), packet);
if (err < 0) {
if (err == AVERROR_EOF)
throw END_OF_FILE();
else {
throw IO_ERROR();
}
}
}
......
......@@ -50,11 +50,13 @@ public:
AVStream* getStream(StreamPrediction);
bool isReady() noexcept;
void closeCustomIO();
protected:
Utils::AVFormatContextShared fmt;
std::string path;
bool isCustomIO;
std::shared_ptr<void> customProto;
std::shared_ptr<IOProto::IOProtoInterface> customProto;
};
......
......@@ -20,14 +20,23 @@ enum RW_FLAG {
write
};
class IOProtoInterface {
public:
virtual ~IOProtoInterface() {};
virtual void close() = 0;
};
/* IOProtocol used to wrap IO Protocol logics
* and transform into AVIOContext */
template<typename T>
class IOProtocol {
class IOProtocol: public IOProtoInterface {
public:
IOProtocol(std::string name, RW_FLAG flag, void *priv):
name(name), flag(flag), io(nullptr), priv(priv) {}
~IOProtocol() {};
int read_packet(void *priv, uint8_t *buf, int bufSize) {
return static_cast<T*>(this)->read_packet_internal(priv, buf, bufSize);
}
......@@ -40,6 +49,10 @@ public:
return static_cast<T*>(this)->seek_packet_internal(opaque, offset, whence);
}
void close() {
static_cast<T*>(this)->close_internal();
}
AVIOContext* to_avioctx() noexcept {
if (io == nullptr) {
......
......@@ -18,9 +18,9 @@ struct BufferInfo {
uint8_t *buffer;
uint8_t *pos;
size_t remain;
bool eof;
};
bool eof = false;
BufferInfo current;
queue<BufferInfo> externalBuffers;
......@@ -29,6 +29,17 @@ static bool isRleaseExtBuf = false;
static bool debugging = true;
constexpr size_t buffMaxSize = 33554432;
uint64_t dataSize = 0;
uint8_t buff[buffMaxSize];
uint8_t *buffCurrent = buff;
uint8_t *buffEnd = buff + buffMaxSize;
int numOfFrames() {
return externalBuffers.size();
}
void config_releaseExtBuf(bool onoff) {
isRleaseExtBuf = onoff;
......@@ -36,27 +47,31 @@ void config_releaseExtBuf(bool onoff) {
/* Note: The passed buf should be full filled */
void attachBuffer(uint8_t *buf, size_t bufSize) {
externalBuffers.push({ buf, buf, bufSize, false });
externalBuffers.push({ buf, buf, bufSize });
}
int TransientMemProto::read_packet_internal(void *priv, uint8_t *buf, int bufSize) {
size_t readSize = 0;
if(flag == write || bufSize < 0 || buf == nullptr) {
AVERROR(EINVAL);
}
// No Datas
if (current.remain == 0 && externalBuffers.empty()) {
return AVERROR(EAGAIN);
if (eof)
return AVERROR_EOF;
else
return AVERROR(EAGAIN);
}
if (current.remain == 0) {
current = externalBuffers.front();
externalBuffers.pop();
if (current.eof) return AVERROR_EOF;
}
size_t readSize = std::min((size_t)bufSize, current.remain);
readSize = std::min((size_t)bufSize, current.remain);
// Read data
memcpy(buf, current.pos, readSize);
......@@ -86,5 +101,9 @@ int64_t TransientMemProto::seek_packet_internal(void *opaque, int64_t offset, in
return 0;
}
void TransientMemProto::close_internal() {
eof = true;
}
}
}
......@@ -7,9 +7,13 @@
namespace IOProto {
namespace TransientMemProto {
extern uint64_t dataSize;
void config_releaseExtBuf(bool onoff);
bool isEmpty();
int numOfFrames();
/* Note: The passed buf should be full filled */
void attachBuffer(uint8_t *buf, size_t bufSize);
......@@ -28,6 +32,8 @@ public:
int64_t seek_packet_internal(void *opaque, int64_t offset, int whence);
void close_internal();
};
}
......
......@@ -42,15 +42,13 @@ static AVFormatContext* AVFormatOutputContextConstructor(
AVFormatContext *ctx = nullptr;
if (customFormat != nullptr)
path = "";
if (avformat_alloc_output_context2(&ctx, customFormat, nullptr, path.c_str()) < 0) {
if (avformat_alloc_output_context2(&ctx, nullptr, nullptr, path.c_str()) < 0) {
return nullptr;
}
if (customIO != nullptr) {
ctx->pb = customIO;
ctx->flags = ctx->flags | AVFMT_FLAG_CUSTOM_IO;
}
......
......@@ -27,8 +27,8 @@ protected:
}
void TearDown() override {
std::string cmd = "rm -f " + outFilePath;
system(cmd.c_str());
//std::string cmd = "rm -f " + outFilePath;
//system(cmd.c_str());
}
std::string inFilePath = "./resources/small_bunny_1080p_60fps.mp4";
......@@ -43,8 +43,7 @@ protected:
void SetUp() override {
TrMemProto::TransientMemProto *outProto =
new TrMemProto::TransientMemProto(nullptr, IOProto::write);
AVOutputFormat *h264Output = av_guess_format("h264", nullptr, nullptr);
outCtxCustom = new IOCtx::OutCtx("", outProto, h264Output);
outCtxCustom = new IOCtx::OutCtx("a.264", outProto, nullptr);
AVStream *is = iCtx.getStream([](AVStream *s) {
return s->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
......@@ -53,9 +52,6 @@ protected:
throw std::runtime_error("SetUp Failed");
}
outCtxCustom->writeHeader();
if (oCtx.newStream(is->codecpar) == IOCtx::ERROR)
throw std::runtime_error("Failed to init fixture");
oCtx.writeHeader();
}
std::string inFilePath = "./resources/small_bunny_1080p_60fps.mp4";
......@@ -67,6 +63,7 @@ protected:
IOCtx::OutCtx oCtx { outFilePath };
};
#if 0
TEST_F(IOCTX_With_Default_Proto_Fixture, Description) {
AVPacket packet;
......@@ -91,35 +88,73 @@ TEST_F(IOCTX_With_Default_Proto_Fixture, Description) {
ASSERT_TRUE(Utils::isVideoValid(outFilePath));
}
#endif
TEST_F(IOCTX_With_TransientMem_Proto_Fixture, Description) {
AVPacket *packet = av_packet_alloc();
for (int i = 0; i < 200; ++i) {
for (int i = 0; i < 300; ++i) {
iCtx.readFrame(packet);
outCtxCustom->writeFrame(packet);
av_packet_unref(packet);
}
outCtxCustom->closeCustomIO();
std::cerr << "Data Size " << IOProto::TransientMemProto::dataSize << std::endl;
TrMemProto::TransientMemProto *inProto =
new TrMemProto::TransientMemProto(nullptr, IOProto::read);
inCtxCustom = new IOCtx::InCtx("", inProto);
AVStream *s = inCtxCustom->getStream([](AVStream *s) {
return s->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
});
try{
while (true) {
iCtx.readFrame(packet);
outCtxCustom->writeFrame(packet);
if (oCtx.newStream(s->codecpar) == IOCtx::ERROR)
throw std::runtime_error("Failed to init fixture");
oCtx.writeHeader();
// Make sure all buffered datas is used
inCtxCustom->readFrame(packet);
int i = 0;
oCtx.writeFrame(packet);
int timescale = 90000;
int fps = 30;
AVRational tb = av_make_q(1, timescale);
int duration = timescale/fps;
int lastPTS = 0, lastDTS = 0;
av_packet_unref(packet);
}
try{
while (true) {
// Make sure all buffered datas is used
inCtxCustom->readFrame(packet);
if (i == 0) {
packet->pts = 0;
packet->dts = -duration;
packet->duration = duration;
lastPTS = packet->pts;
lastDTS = packet->dts;
} else {
packet->pts = lastPTS + duration;
packet->dts = lastDTS + duration;
lastPTS += duration;
lastDTS += duration;
}
packet->stream_index = 0;
packet->pos = -1;
oCtx.writeFrame(packet);
av_packet_unref(packet);
++i;
}
} catch (IOCtx::END_OF_FILE e) {}
printf("%d\n", i);
oCtx.writeTrailer();
inCtxCustom->closeCustomIO();
ASSERT_TRUE(Utils::isVideoValid(outFilePath));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment