forked from mia/Aegisub
Reduce error-handling bloat a bit
This commit is contained in:
parent
b0f4c9f1ad
commit
d5dde6cff2
4 changed files with 59 additions and 64 deletions
|
@ -77,27 +77,7 @@ void push_value(lua_State *L, std::vector<T> const& value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int exception_wrapper(lua_State *L, int (*func)(lua_State *L)) {
|
int exception_wrapper(lua_State *L, int (*func)(lua_State *L));
|
||||||
try {
|
|
||||||
return func(L);
|
|
||||||
}
|
|
||||||
catch (agi::Exception const& e) {
|
|
||||||
push_value(L, e.GetMessage());
|
|
||||||
return lua_error(L);
|
|
||||||
}
|
|
||||||
catch (std::exception const& e) {
|
|
||||||
push_value(L, e.what());
|
|
||||||
return lua_error(L);
|
|
||||||
}
|
|
||||||
catch (error_tag) {
|
|
||||||
// Error message is already on the stack
|
|
||||||
return lua_error(L);
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
std::terminate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wrap a function which may throw exceptions and make it trigger lua errors
|
/// Wrap a function which may throw exceptions and make it trigger lua errors
|
||||||
/// whenever it throws
|
/// whenever it throws
|
||||||
template<int (*func)(lua_State *L)>
|
template<int (*func)(lua_State *L)>
|
||||||
|
|
|
@ -213,6 +213,27 @@ void argcheck(lua_State *L, bool cond, int narg, const char *msg) {
|
||||||
if (!cond) argerror(L, narg, msg);
|
if (!cond) argerror(L, narg, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int exception_wrapper(lua_State *L, int (*func)(lua_State *L)) {
|
||||||
|
try {
|
||||||
|
return func(L);
|
||||||
|
}
|
||||||
|
catch (agi::Exception const& e) {
|
||||||
|
push_value(L, e.GetMessage());
|
||||||
|
return lua_error(L);
|
||||||
|
}
|
||||||
|
catch (std::exception const& e) {
|
||||||
|
push_value(L, e.what());
|
||||||
|
return lua_error(L);
|
||||||
|
}
|
||||||
|
catch (error_tag) {
|
||||||
|
// Error message is already on the stack
|
||||||
|
return lua_error(L);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
std::terminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
void LuaStackcheck::check_stack(int additional) {
|
void LuaStackcheck::check_stack(int additional) {
|
||||||
int top = lua_gettop(L);
|
int top = lua_gettop(L);
|
||||||
|
|
|
@ -35,13 +35,20 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "video_frame.h"
|
#include "video_frame.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template<typename Exception>
|
||||||
|
BOOST_NOINLINE void throw_error(GLenum err, const char *msg) {
|
||||||
|
LOG_E("video/out/gl") << msg << " failed with error code " << err;
|
||||||
|
throw Exception(msg, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define DO_CHECK_ERROR(cmd, Exception, msg) \
|
#define DO_CHECK_ERROR(cmd, Exception, msg) \
|
||||||
do { \
|
do { \
|
||||||
cmd; \
|
cmd; \
|
||||||
if (GLenum err = glGetError()) { \
|
GLenum err = glGetError(); \
|
||||||
LOG_E("video/out/gl") << msg << " failed with error code " << err; \
|
if (BOOST_UNLIKELY(err)) \
|
||||||
throw Exception(msg, err); \
|
throw_error<Exception>(err, msg); \
|
||||||
} \
|
|
||||||
} while(0);
|
} while(0);
|
||||||
#define CHECK_INIT_ERROR(cmd) DO_CHECK_ERROR(cmd, VideoOutInitException, #cmd)
|
#define CHECK_INIT_ERROR(cmd) DO_CHECK_ERROR(cmd, VideoOutInitException, #cmd)
|
||||||
#define CHECK_ERROR(cmd) DO_CHECK_ERROR(cmd, VideoOutRenderException, #cmd)
|
#define CHECK_ERROR(cmd) DO_CHECK_ERROR(cmd, VideoOutRenderException, #cmd)
|
||||||
|
|
|
@ -134,7 +134,6 @@ class YUV4MPEGVideoProvider final : public VideoProvider {
|
||||||
/// each frame header can be found
|
/// each frame header can be found
|
||||||
std::vector<uint64_t> seek_table;
|
std::vector<uint64_t> seek_table;
|
||||||
|
|
||||||
void CheckFileFormat();
|
|
||||||
void ParseFileHeader(const std::vector<std::string>& tags);
|
void ParseFileHeader(const std::vector<std::string>& tags);
|
||||||
Y4M_FrameFlags ParseFrameHeader(const std::vector<std::string>& tags);
|
Y4M_FrameFlags ParseFrameHeader(const std::vector<std::string>& tags);
|
||||||
std::vector<std::string> ReadHeader(uint64_t &startpos);
|
std::vector<std::string> ReadHeader(uint64_t &startpos);
|
||||||
|
@ -162,7 +161,10 @@ public:
|
||||||
YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(agi::fs::path const& filename)
|
YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(agi::fs::path const& filename)
|
||||||
: file(filename)
|
: file(filename)
|
||||||
{
|
{
|
||||||
CheckFileFormat();
|
if (file.size() < 10)
|
||||||
|
throw VideoNotSupported("File is not a YUV4MPEG file (too small)");
|
||||||
|
if (strncmp("YUV4MPEG2 ", file.read(0, 10), 10))
|
||||||
|
throw VideoNotSupported("File is not a YUV4MPEG file (bad magic)");
|
||||||
|
|
||||||
uint64_t pos = 0;
|
uint64_t pos = 0;
|
||||||
ParseFileHeader(ReadHeader(pos));
|
ParseFileHeader(ReadHeader(pos));
|
||||||
|
@ -185,10 +187,8 @@ YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(agi::fs::path const& filename)
|
||||||
case Y4M_PIXFMT_420MPEG2:
|
case Y4M_PIXFMT_420MPEG2:
|
||||||
case Y4M_PIXFMT_420PALDV:
|
case Y4M_PIXFMT_420PALDV:
|
||||||
chroma_sz = (w * h) >> 2; break;
|
chroma_sz = (w * h) >> 2; break;
|
||||||
case Y4M_PIXFMT_422:
|
|
||||||
chroma_sz = (w * h) >> 1; break;
|
|
||||||
/// @todo add support for more pixel formats
|
|
||||||
default:
|
default:
|
||||||
|
/// @todo add support for more pixel formats
|
||||||
throw VideoOpenError("Unsupported pixel format");
|
throw VideoOpenError("Unsupported pixel format");
|
||||||
}
|
}
|
||||||
frame_sz = luma_sz + chroma_sz*2;
|
frame_sz = luma_sz + chroma_sz*2;
|
||||||
|
@ -198,16 +198,6 @@ YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(agi::fs::path const& filename)
|
||||||
throw VideoOpenError("Unable to determine file length");
|
throw VideoOpenError("Unable to determine file length");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Checks if the file is an YUV4MPEG file or not
|
|
||||||
/// Note that it reports the error by throwing an exception,
|
|
||||||
/// not by returning a false value.
|
|
||||||
void YUV4MPEGVideoProvider::CheckFileFormat() {
|
|
||||||
if (file.size() < 10)
|
|
||||||
throw VideoNotSupported("CheckFileFormat: File is not a YUV4MPEG file (too small)");
|
|
||||||
if (strncmp("YUV4MPEG2 ", file.read(0, 10), 10))
|
|
||||||
throw VideoNotSupported("CheckFileFormat: File is not a YUV4MPEG file (bad magic)");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Read a frame or file header at a given file position
|
/// @brief Read a frame or file header at a given file position
|
||||||
/// @param startpos The byte offset at where to start reading
|
/// @param startpos The byte offset at where to start reading
|
||||||
/// @return A list of parameters
|
/// @return A list of parameters
|
||||||
|
@ -266,22 +256,23 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<std::string>& tags
|
||||||
char type = tags[i][0];
|
char type = tags[i][0];
|
||||||
std::string tag = tags[i].substr(1);
|
std::string tag = tags[i].substr(1);
|
||||||
|
|
||||||
|
const char *err = nullptr;
|
||||||
if (type == 'W') {
|
if (type == 'W') {
|
||||||
if (!agi::util::try_parse(tag, &t_w))
|
if (!agi::util::try_parse(tag, &t_w))
|
||||||
throw VideoOpenError("ParseFileHeader: invalid width");
|
err = "invalid width";
|
||||||
}
|
}
|
||||||
else if (type == 'H') {
|
else if (type == 'H') {
|
||||||
if (!agi::util::try_parse(tag, &t_h))
|
if (!agi::util::try_parse(tag, &t_h))
|
||||||
throw VideoOpenError("ParseFileHeader: invalid height");
|
err = "invalid height";
|
||||||
}
|
}
|
||||||
else if (type == 'F') {
|
else if (type == 'F') {
|
||||||
size_t pos = tag.find(':');
|
size_t pos = tag.find(':');
|
||||||
if (pos == tag.npos)
|
if (pos == tag.npos)
|
||||||
throw VideoOpenError("ParseFileHeader: invalid framerate");
|
err = "invalid framerate";
|
||||||
|
|
||||||
if (!agi::util::try_parse(tag.substr(0, pos), &t_fps_num) ||
|
if (!agi::util::try_parse(tag.substr(0, pos), &t_fps_num) ||
|
||||||
!agi::util::try_parse(tag.substr(pos + 1), &t_fps_den))
|
!agi::util::try_parse(tag.substr(pos + 1), &t_fps_den))
|
||||||
throw VideoOpenError("ParseFileHeader: invalid framerate");
|
err = "invalid framerate";
|
||||||
}
|
}
|
||||||
else if (type == 'C') {
|
else if (type == 'C') {
|
||||||
// technically this should probably be case sensitive,
|
// technically this should probably be case sensitive,
|
||||||
|
@ -297,7 +288,7 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<std::string>& tags
|
||||||
else if (tag == "444alpha") t_pixfmt = Y4M_PIXFMT_444ALPHA;
|
else if (tag == "444alpha") t_pixfmt = Y4M_PIXFMT_444ALPHA;
|
||||||
else if (tag == "mono") t_pixfmt = Y4M_PIXFMT_MONO;
|
else if (tag == "mono") t_pixfmt = Y4M_PIXFMT_MONO;
|
||||||
else
|
else
|
||||||
throw VideoOpenError("ParseFileHeader: invalid or unknown colorspace");
|
err = "invalid or unknown colorspace";
|
||||||
}
|
}
|
||||||
else if (type == 'I') {
|
else if (type == 'I') {
|
||||||
boost::to_lower(tag);
|
boost::to_lower(tag);
|
||||||
|
@ -307,10 +298,13 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<std::string>& tags
|
||||||
else if (tag == "m") t_imode = Y4M_ILACE_MIXED;
|
else if (tag == "m") t_imode = Y4M_ILACE_MIXED;
|
||||||
else if (tag == "?") t_imode = Y4M_ILACE_UNKNOWN;
|
else if (tag == "?") t_imode = Y4M_ILACE_UNKNOWN;
|
||||||
else
|
else
|
||||||
throw VideoOpenError("ParseFileHeader: invalid or unknown interlacing mode");
|
err = "invalid or unknown interlacing mode";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LOG_D("provider/video/yuv4mpeg") << "Unparsed tag: " << tags[i];
|
LOG_D("provider/video/yuv4mpeg") << "Unparsed tag: " << tags[i];
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
throw VideoOpenError(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The point of all this is to allow multiple YUV4MPEG2 headers in a single file
|
// The point of all this is to allow multiple YUV4MPEG2 headers in a single file
|
||||||
|
@ -318,16 +312,19 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<std::string>& tags
|
||||||
// header flags. The spec doesn't explicitly say you have to allow this,
|
// header flags. The spec doesn't explicitly say you have to allow this,
|
||||||
// but the "reference implementation" (mjpegtools) does, so I'm doing it too.
|
// but the "reference implementation" (mjpegtools) does, so I'm doing it too.
|
||||||
if (inited) {
|
if (inited) {
|
||||||
|
const char *err = nullptr;
|
||||||
if (t_w > 0 && t_w != w)
|
if (t_w > 0 && t_w != w)
|
||||||
throw VideoOpenError("ParseFileHeader: illegal width change");
|
err = "illegal width change";
|
||||||
if (t_h > 0 && t_h != h)
|
if (t_h > 0 && t_h != h)
|
||||||
throw VideoOpenError("ParseFileHeader: illegal height change");
|
err = "illegal height change";
|
||||||
if ((t_fps_num > 0 && t_fps_den > 0) && (t_fps_num != fps_rat.num || t_fps_den != fps_rat.den))
|
if ((t_fps_num > 0 && t_fps_den > 0) && (t_fps_num != fps_rat.num || t_fps_den != fps_rat.den))
|
||||||
throw VideoOpenError("ParseFileHeader: illegal framerate change");
|
err = "illegal framerate change";
|
||||||
if (t_pixfmt != Y4M_PIXFMT_NONE && t_pixfmt != pixfmt)
|
if (t_pixfmt != Y4M_PIXFMT_NONE && t_pixfmt != pixfmt)
|
||||||
throw VideoOpenError("ParseFileHeader: illegal colorspace change");
|
err = "illegal colorspace change";
|
||||||
if (t_imode != Y4M_ILACE_NOTSET && t_imode != imode)
|
if (t_imode != Y4M_ILACE_NOTSET && t_imode != imode)
|
||||||
throw VideoOpenError("ParseFileHeader: illegal interlacing mode change");
|
err = "illegal interlacing mode change";
|
||||||
|
if (err)
|
||||||
|
throw VideoOpenError(err);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
w = t_w;
|
w = t_w;
|
||||||
|
@ -346,12 +343,11 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<std::string>& tags
|
||||||
/// @return The flags set, as a binary mask
|
/// @return The flags set, as a binary mask
|
||||||
/// This function is currently unimplemented (it will always return Y4M_FFLAG_NONE).
|
/// This function is currently unimplemented (it will always return Y4M_FFLAG_NONE).
|
||||||
YUV4MPEGVideoProvider::Y4M_FrameFlags YUV4MPEGVideoProvider::ParseFrameHeader(const std::vector<std::string>& tags) {
|
YUV4MPEGVideoProvider::Y4M_FrameFlags YUV4MPEGVideoProvider::ParseFrameHeader(const std::vector<std::string>& tags) {
|
||||||
if (tags.front() != "FRAME")
|
if (tags.front() == "FRAME")
|
||||||
throw VideoOpenError("ParseFrameHeader: malformed frame header (bad magic)");
|
return Y4M_FFLAG_NONE;
|
||||||
|
|
||||||
/// @todo implement parsing of frame flags
|
/// @todo implement parsing of frame flags
|
||||||
|
throw VideoOpenError("ParseFrameHeader: malformed frame header (bad magic)");
|
||||||
return Y4M_FFLAG_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Indexes the file
|
/// @brief Indexes the file
|
||||||
|
@ -395,15 +391,6 @@ void YUV4MPEGVideoProvider::GetFrame(int n, VideoFrame &frame) {
|
||||||
n = mid(0, n, num_frames - 1);
|
n = mid(0, n, num_frames - 1);
|
||||||
|
|
||||||
int uv_width = w / 2;
|
int uv_width = w / 2;
|
||||||
switch (pixfmt) {
|
|
||||||
case Y4M_PIXFMT_420JPEG:
|
|
||||||
case Y4M_PIXFMT_420MPEG2:
|
|
||||||
case Y4M_PIXFMT_420PALDV:
|
|
||||||
break;
|
|
||||||
/// @todo add support for more pixel formats
|
|
||||||
default:
|
|
||||||
throw VideoNotSupported("YUV4MPEG video provider: GetFrame: Unsupported source colorspace");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto src_y = reinterpret_cast<const unsigned char *>(file.read(seek_table[n], luma_sz + chroma_sz * 2));
|
auto src_y = reinterpret_cast<const unsigned char *>(file.read(seek_table[n], luma_sz + chroma_sz * 2));
|
||||||
auto src_u = src_y + luma_sz;
|
auto src_u = src_y + luma_sz;
|
||||||
|
|
Loading…
Reference in a new issue