[x265] [PATCH] y4m: make file reading threaded
kavitha at multicorewareinc.com
kavitha at multicorewareinc.com
Tue Oct 15 10:45:46 CEST 2013
# HG changeset patch
# User Kavitha Sampath <kavitha at multicorewareinc.com>
# Date 1381825927 -19800
# Tue Oct 15 14:02:07 2013 +0530
# Node ID 5a94d3e1d4fe769b8dca27f2a1c61784248adaff
# Parent 1a85d8814346efdb984ea9eae24d1b06b973e9a8
y4m: make file reading threaded
diff -r 1a85d8814346 -r 5a94d3e1d4fe source/input/input.h
--- a/source/input/input.h Tue Oct 15 12:45:58 2013 +0530
+++ b/source/input/input.h Tue Oct 15 14:02:07 2013 +0530
@@ -24,6 +24,14 @@
#ifndef X265_INPUT_H
#define X265_INPUT_H
+#define ENABLE_THREAD
+#define MIN_FRAME_WIDTH 64
+#define MAX_FRAME_WIDTH 8192
+#define MIN_FRAME_HEIGHT 64
+#define MAX_FRAME_HEIGHT 4320
+#define MIN_FRAME_RATE 1
+#define MAX_FRAME_RATE 300
+
#include "x265.h"
namespace x265 {
diff -r 1a85d8814346 -r 5a94d3e1d4fe source/input/y4m.cpp
--- a/source/input/y4m.cpp Tue Oct 15 12:45:58 2013 +0530
+++ b/source/input/y4m.cpp Tue Oct 15 14:02:07 2013 +0530
@@ -23,6 +23,7 @@
#include "y4m.h"
#include "PPA/ppa.h"
+#include "common.h"
#include <stdio.h>
#include <string.h>
@@ -32,25 +33,53 @@
Y4MInput::Y4MInput(const char *filename)
{
ifs.open(filename, ios::binary | ios::in);
+ threadActive = false;
if (!ifs.fail())
{
- parseHeader();
- buf = new char[3 * width * height / 2];
+ if (parseHeader())
+ {
+ threadActive = true;
+#if defined(ENABLE_THREAD)
+ for (int i = 0; i < QUEUE_SIZE; i++)
+ {
+ buf[i] = new char[3 * width * height / 2];
+ if ( buf[i] == NULL)
+ {
+ x265_log(NULL, X265_LOG_ERROR, "y4m: buffer allocation failure, aborting");
+ threadActive = false;
+ }
+ }
+ head = 0;
+ tail = 0;
+ start();
+#else
+ buf = new char[3 * width * height / 2];
+#endif
+ }
}
+ if (!threadActive)
+ ifs.close();
}
Y4MInput::~Y4MInput()
{
ifs.close();
+#if defined(ENABLE_THREAD)
+ for (int i = 0; i < QUEUE_SIZE; i++)
+ {
+ delete[] buf[i];
+ }
+#else
delete[] buf;
+#endif
}
-void Y4MInput::parseHeader()
+bool Y4MInput::parseHeader()
{
- int t_width = 0;
- int t_height = 0;
- int t_rateNumerator = 0;
- int t_rateDenominator = 0;
+ int frame_width = 0;
+ int frame_height = 0;
+ int frame_rateNumerator = 0;
+ int frame_rateDenominator = 0;
while (ifs)
{
@@ -67,7 +96,7 @@
switch (ifs.get())
{
case 'W':
- t_width = 0;
+ frame_width = 0;
while (ifs)
{
byte = ifs.get();
@@ -78,14 +107,13 @@
}
else
{
- t_width = t_width * 10 + (byte - '0');
+ frame_width = frame_width * 10 + (byte - '0');
}
}
-
break;
case 'H':
- t_height = 0;
+ frame_height = 0;
while (ifs)
{
byte = ifs.get();
@@ -95,21 +123,21 @@
}
else
{
- t_height = t_height * 10 + (byte - '0');
+ frame_height = frame_height * 10 + (byte - '0');
}
}
break;
case 'F':
- t_rateNumerator = 0;
- t_rateDenominator = 0;
+ frame_rateNumerator = 0;
+ frame_rateDenominator = 0;
while (ifs)
{
byte = ifs.get();
if (byte == '.')
{
- t_rateDenominator = 1;
+ frame_rateDenominator = 1;
while (ifs)
{
byte = ifs.get();
@@ -119,8 +147,8 @@
}
else
{
- t_rateNumerator = t_rateNumerator * 10 + (byte - '0');
- t_rateDenominator = t_rateDenominator * 10;
+ frame_rateNumerator = frame_rateNumerator * 10 + (byte - '0');
+ frame_rateDenominator = frame_rateDenominator * 10;
}
}
@@ -136,14 +164,14 @@
break;
}
else
- t_rateDenominator = t_rateDenominator * 10 + (byte - '0');
+ frame_rateDenominator = frame_rateDenominator * 10 + (byte - '0');
}
break;
}
else
{
- t_rateNumerator = t_rateNumerator * 10 + (byte - '0');
+ frame_rateNumerator = frame_rateNumerator * 10 + (byte - '0');
}
}
@@ -170,10 +198,16 @@
//TODO need to include code for parsing colourspace from file.
- width = t_width;
- height = t_height;
- rateNum = t_rateNumerator;
- rateDenom = t_rateDenominator;
+ if (frame_width < MIN_FRAME_WIDTH || frame_width > MAX_FRAME_WIDTH ||
+ frame_height < MIN_FRAME_HEIGHT || frame_width > MAX_FRAME_HEIGHT ||
+ (frame_rateNumerator / frame_rateDenominator) < 1 || (frame_rateNumerator / frame_rateDenominator) > MAX_FRAME_RATE)
+ return false;
+
+ width = frame_width;
+ height = frame_height;
+ rateNum = frame_rateNumerator;
+ rateDenom = frame_rateDenominator;
+ return true;
}
static const char header[] = "FRAME";
@@ -199,6 +233,80 @@
}
}
+#if defined(ENABLE_THREAD)
+bool Y4MInput::readPicture(x265_picture_t& pic)
+{
+ PPAStartCpuEventFunc(read_yuv);
+ if (!threadActive)
+ return false;
+ while (head == tail)
+ {
+ notEmpty.wait();
+ }
+ if (!frameStat[head])
+ return false;
+
+ pic.planes[0] = buf[head];
+
+ pic.planes[1] = buf[head] + width * height;
+
+ pic.planes[2] = buf[head] + width * height + ((width * height) >> 2);
+
+ pic.bitDepth = 8;
+
+ pic.stride[0] = width;
+
+ pic.stride[1] = pic.stride[2] = pic.stride[0] >> 1;
+ head = (head + 1) % QUEUE_SIZE;
+ notFull.trigger();
+
+ PPAStopCpuEventFunc(read_yuv);
+ return true;
+}
+
+void Y4MInput::threadMain()
+{
+ do
+ {
+ if (!populateFrameQueue())
+ break;
+ }
+ while (threadActive);
+}
+
+bool Y4MInput::populateFrameQueue()
+{
+ /* strip off the FRAME header */
+ char hbuf[sizeof(header)];
+ ifs.read(hbuf, strlen(header));
+ if (!ifs || memcmp(hbuf, header, strlen(header)))
+ {
+ if (ifs)
+ x265_log(NULL, X265_LOG_ERROR, "y4m: frame header missing");
+ return false;
+ }
+ /* consume bytes up to line feed */
+ int byte = ifs.get();
+ while (byte != '\n' && !ifs)
+ {
+ byte = ifs.get();
+ }
+ const size_t count = width * height * 3 / 2;
+ while ((tail + 1) % QUEUE_SIZE == head)
+ {
+ notFull.wait();
+ if (!threadActive)
+ break;
+ }
+ ifs.read(buf[tail], count);
+ frameStat[tail] = ifs.good();
+ if (!frameStat[tail])
+ return false;
+ tail = (tail + 1) % QUEUE_SIZE;
+ notEmpty.trigger();
+ return true;
+}
+#else
bool Y4MInput::readPicture(x265_picture_t& pic)
{
PPAStartCpuEventFunc(read_yuv);
@@ -206,9 +314,9 @@
/* strip off the FRAME header */
char hbuf[sizeof(header)];
ifs.read(hbuf, strlen(header));
- if (!ifs || strncmp(hbuf, header, strlen(header)))
+ if (!ifs || memcmp(hbuf, header, strlen(header)))
{
- fprintf(stderr, "Y4M frame header missing\n");
+ x265_log(NULL, X265_LOG_ERROR, "y4m: frame header missing");
return false;
}
@@ -238,3 +346,13 @@
return ifs.good();
}
+#endif
+void Y4MInput::release()
+{
+#if defined(ENABLE_THREAD)
+ threadActive = false;
+ notFull.trigger();
+ stop();
+#endif
+ delete this;
+}
diff -r 1a85d8814346 -r 5a94d3e1d4fe source/input/y4m.h
--- a/source/input/y4m.h Tue Oct 15 12:45:58 2013 +0530
+++ b/source/input/y4m.h Tue Oct 15 14:02:07 2013 +0530
@@ -27,10 +27,19 @@
#include "input.h"
#include <fstream>
+#if defined(ENABLE_THREAD)
+#define QUEUE_SIZE 5
+#include "threading.h"
+#endif
+
namespace x265 {
// x265 private namespace
+#if defined(ENABLE_THREAD)
+class Y4MInput : public Input, public Thread
+#else
class Y4MInput : public Input
+#endif
{
protected:
@@ -42,11 +51,26 @@
int height;
- char* buf;
+ bool threadActive;
+#if defined(ENABLE_THREAD)
+ volatile int head;
+
+ volatile int tail;
+
+ bool frameStat[QUEUE_SIZE];
+
+ char* buf[QUEUE_SIZE];
+
+ Event notFull;
+
+ Event notEmpty;
+#else
+ char *buf;
+#endif
std::ifstream ifs;
- void parseHeader();
+ bool parseHeader();
public:
@@ -66,9 +90,9 @@
bool isEof() const { return ifs.eof(); }
- bool isFail() { return !ifs.is_open(); }
+ bool isFail() { return !(ifs.is_open() && threadActive); }
- void release() { delete this; }
+ void release();
int guessFrameCount();
@@ -76,6 +100,14 @@
bool readPicture(x265_picture_t&);
+#if defined(ENABLE_THREAD)
+
+ void threadMain();
+
+ bool populateFrameQueue();
+
+#endif
+
const char *getName() const { return "y4m"; }
};
}
More information about the x265-devel
mailing list