From 1a182098fc71dcdb523b7ed2b82563b0e3a88a36 Mon Sep 17 00:00:00 2001 From: Karl Blomster Date: Fri, 7 Aug 2009 19:59:37 +0000 Subject: [PATCH] Document the Y4M video provider. Originally committed to SVN as r3376. --- aegisub/src/video_provider_yuv4mpeg.cpp | 126 ++++++--------- aegisub/src/video_provider_yuv4mpeg.h | 204 +++++++----------------- 2 files changed, 103 insertions(+), 227 deletions(-) diff --git a/aegisub/src/video_provider_yuv4mpeg.cpp b/aegisub/src/video_provider_yuv4mpeg.cpp index f68e4726b..e8e6bf3c5 100644 --- a/aegisub/src/video_provider_yuv4mpeg.cpp +++ b/aegisub/src/video_provider_yuv4mpeg.cpp @@ -42,20 +42,15 @@ // (yes, really) // With cstdio it's at least possible to work around the problem... #ifdef _MSC_VER - -/// DOCME #define fseeko _fseeki64 - -/// DOCME #define ftello _ftelli64 #endif -/// @brief DOCME -/// @param filename -/// +/// @brief Constructor +/// @param filename The filename to open YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(wxString filename) { sf = NULL; w = 0; @@ -86,18 +81,14 @@ YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(wxString filename) { } - -/// @brief DOCME -/// +/// @brief Destructor YUV4MPEGVideoProvider::~YUV4MPEGVideoProvider() { Close(); } - -/// @brief DOCME -/// @param _filename -/// +/// @brief Open a video file +/// @param _filename The video file to open void YUV4MPEGVideoProvider::LoadVideo(const wxString _filename) { Close(); @@ -128,17 +119,19 @@ void YUV4MPEGVideoProvider::LoadVideo(const wxString _filename) { if (imode == Y4M_ILACE_NOTSET) imode = Y4M_ILACE_UNKNOWN; + luma_sz = w * h; switch (pixfmt) { case Y4M_PIXFMT_420JPEG: case Y4M_PIXFMT_420MPEG2: case Y4M_PIXFMT_420PALDV: - frame_sz = (w * h * 3) / 2; break; + chroma_sz = (w * h) / 2; break; case Y4M_PIXFMT_422: - frame_sz = (w * h * 2); break; - // TODO: add support for more pixel formats + chroma_sz = (w / 2) * h; break; // should be safe to assume that width is mod2 + /// @todo add support for more pixel formats default: - throw wxString(_T("Unsupported colorspace")); + throw wxString(_T("Unsupported pixel format")); } + frame_sz = luma_sz + chroma_sz*2; num_frames = IndexFile(); if (num_frames <= 0 || seek_table.empty()) @@ -149,9 +142,7 @@ void YUV4MPEGVideoProvider::LoadVideo(const wxString _filename) { } - -/// @brief DOCME -/// +/// @brief Closes the currently open file (if any) and resets reader state void YUV4MPEGVideoProvider::Close() { seek_table.clear(); if (sf) @@ -160,10 +151,9 @@ void YUV4MPEGVideoProvider::Close() { } - -/// @brief verify that the file is actually a YUV4MPEG file -/// @return -/// +/// @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() { char buf[10]; if (fread(buf, 10, 1, sf) != 1) @@ -175,12 +165,10 @@ void YUV4MPEGVideoProvider::CheckFileFormat() { } - -/// @brief read a frame or file header and return a list of its parameters -/// @param startpos -/// @param reset_pos -/// @return -/// +/// @brief Read a frame or file header at a given file position +/// @param startpos The byte offset at where to start reading +/// @param reset_pos If true, the function will reset the file position to what it was before the function call before returning +/// @return A list of parameters std::vector YUV4MPEGVideoProvider::ReadHeader(int64_t startpos, bool reset_pos) { int64_t oldpos = ftello(sf); std::vector tags; @@ -230,10 +218,8 @@ std::vector YUV4MPEGVideoProvider::ReadHeader(int64_t startpos, bool r } - -/// @brief parse a file header and set file properties -/// @param tags -/// +/// @brief Parses a list of parameters and sets reader state accordingly +/// @param tags The list of parameters to parse void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector& tags) { if (tags.size() <= 1) throw wxString(_T("ParseFileHeader: contentless header")); @@ -318,32 +304,32 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector& tags) { h = t_h; fps_rat.num = t_fps_num; fps_rat.den = t_fps_den; - pixfmt = t_pixfmt != Y4M_PIXFMT_NONE ? t_pixfmt : Y4M_PIXFMT_420JPEG; - imode = t_imode != Y4M_ILACE_NOTSET ? t_imode : Y4M_ILACE_UNKNOWN; + pixfmt = t_pixfmt != Y4M_PIXFMT_NONE ? t_pixfmt : Y4M_PIXFMT_420JPEG; + imode = t_imode != Y4M_ILACE_NOTSET ? t_imode : Y4M_ILACE_UNKNOWN; inited = true; } } - -/// @brief parse a frame header (currently unused) -/// @param tags -/// @return -/// +/// @brief Parses a frame header +/// @param tags The list of parameters to parse +/// @return The flags set, as a binary mask +/// This function is currently unimplemented (it will always return Y4M_FFLAG_NONE). YUV4MPEGVideoProvider::Y4M_FrameFlags YUV4MPEGVideoProvider::ParseFrameHeader(const std::vector& tags) { if (tags.front().Cmp(_("FRAME"))) throw wxString(_T("ParseFrameHeader: malformed frame header (bad magic)")); - // TODO: implement parsing of rff flags etc + /// @todo implement parsing of frame flags return Y4M_FFLAG_NONE; } - -/// @brief index the file, i.e. find all frames and their flags -/// @return -/// +/// @brief Indexes the file +/// @return The number of frames found in the file +/// This function goes through the file, finds and parses all file and frame headers, +/// and creates a seek table that lists the byte positions of all frames so seeking +/// can easily be done. int YUV4MPEGVideoProvider::IndexFile() { int framecount = 0; int64_t curpos = ftello(sf); @@ -375,7 +361,7 @@ int YUV4MPEGVideoProvider::IndexFile() { throw wxString::Format(_T("IndexFile: failed seeking to position %d"), curpos + frame_sz); } else { - // TODO: implement this + /// @todo implement rff flags etc } } @@ -384,10 +370,9 @@ int YUV4MPEGVideoProvider::IndexFile() { -/// @brief DOCME -/// @param n -/// @return -/// +/// @brief Gets a given frame +/// @param n The frame number to return +/// @return The video frame const AegiVideoFrame YUV4MPEGVideoProvider::GetFrame(int n) { // don't try to seek to insane places if (n < 0) @@ -399,15 +384,15 @@ const AegiVideoFrame YUV4MPEGVideoProvider::GetFrame(int n) { VideoFrameFormat src_fmt, dst_fmt; dst_fmt = FORMAT_RGB32; - int uv_width, uv_height; + int uv_width; switch (pixfmt) { case Y4M_PIXFMT_420JPEG: case Y4M_PIXFMT_420MPEG2: case Y4M_PIXFMT_420PALDV: - src_fmt = FORMAT_YV12; uv_width = w / 2; uv_height = h / 2; break; + src_fmt = FORMAT_YV12; uv_width = w / 2; break; case Y4M_PIXFMT_422: - src_fmt = FORMAT_YUY2; uv_width = w / 2; uv_height = h; break; - // TODO: add support for more pixel formats + src_fmt = FORMAT_YUY2; uv_width = w / 2; break; + /// @todo add support for more pixel formats default: throw wxString(_T("YUV4MPEG video provider: GetFrame: Unsupported source colorspace")); } @@ -419,16 +404,17 @@ const AegiVideoFrame YUV4MPEGVideoProvider::GetFrame(int n) { tmp_frame.h = h; tmp_frame.invertChannels = false; tmp_frame.pitch[0] = w; - for (int i=1;i<=2;i++) tmp_frame.pitch[i] = uv_width; + for (int i=1;i<=2;i++) + tmp_frame.pitch[i] = uv_width; tmp_frame.Allocate(); fseeko(sf, seek_table[n], SEEK_SET); size_t ret; - ret = fread(tmp_frame.data[0], w * h, 1, sf); + ret = fread(tmp_frame.data[0], luma_sz, 1, sf); if (ret != 1 || feof(sf) || ferror(sf)) throw wxString(_T("YUV4MPEG video provider: GetFrame: failed to read luma plane")); for (int i = 1; i <= 2; i++) { - ret = fread(tmp_frame.data[i], uv_width * uv_height, 1, sf); + ret = fread(tmp_frame.data[i], chroma_sz, 1, sf); if (ret != 1 || feof(sf) || ferror(sf)) throw wxString(_T("YUV4MPEG video provider: GetFrame: failed to read chroma planes")); } @@ -448,44 +434,24 @@ const AegiVideoFrame YUV4MPEGVideoProvider::GetFrame(int n) { - -/// @brief Utility functions -/// @return -/// +// Utility functions int YUV4MPEGVideoProvider::GetWidth() { return w; } - -/// @brief DOCME -/// @return -/// int YUV4MPEGVideoProvider::GetHeight() { return h; } - -/// @brief DOCME -/// @return -/// int YUV4MPEGVideoProvider::GetFrameCount() { return num_frames; } - -/// @brief DOCME -/// @return -/// int YUV4MPEGVideoProvider::GetPosition() { return cur_fn; } - -/// @brief DOCME -/// double YUV4MPEGVideoProvider::GetFPS() { return double(fps_rat.num) / double(fps_rat.den); } - - diff --git a/aegisub/src/video_provider_yuv4mpeg.h b/aegisub/src/video_provider_yuv4mpeg.h index 5c07542ef..af7d0da1b 100644 --- a/aegisub/src/video_provider_yuv4mpeg.h +++ b/aegisub/src/video_provider_yuv4mpeg.h @@ -45,163 +45,95 @@ #include -/// DOCME +/// the maximum allowed header length, in bytes #define YUV4MPEG_HEADER_MAXLEN 128 /// @class YUV4MPEGVideoProvider -/// @brief DOCME -/// -/// DOCME +/// @brief Implements reading of YUV4MPEG uncompressed video files class YUV4MPEGVideoProvider : public VideoProvider { private: - - /// DOCME + /// Pixel formats enum Y4M_PixelFormat { + Y4M_PIXFMT_NONE = -1, /// not set/unknown - /// DOCME - Y4M_PIXFMT_NONE = -1, + /// 4:2:0 sampling variants. + /// afaict the only difference between these three + /// is the chroma sample location, and nobody cares about that. + Y4M_PIXFMT_420JPEG, /// 4:2:0, H/V centered, for JPEG/MPEG-1 + Y4M_PIXFMT_420MPEG2, /// 4:2:0, H cosited, for MPEG-2 + Y4M_PIXFMT_420PALDV, /// 4:2:0, alternating Cb/Cr, for PAL-DV - /// DOCME - Y4M_PIXFMT_420JPEG, // afaict the only difference between + Y4M_PIXFMT_411, /// 4:1:1, H cosited + Y4M_PIXFMT_422, /// 4:2:2, H cosited + Y4M_PIXFMT_444, /// 4:4:4, i.e. no chroma subsampling + Y4M_PIXFMT_444ALPHA, /// 4:4:4 plus alpha channel - /// DOCME - Y4M_PIXFMT_420MPEG2, // these three is the chroma sample location, - - /// DOCME - Y4M_PIXFMT_420PALDV, // and nobody cares about that. - - /// DOCME - Y4M_PIXFMT_411, - - /// DOCME - Y4M_PIXFMT_422, - - /// DOCME - Y4M_PIXFMT_444, - - /// DOCME - Y4M_PIXFMT_444ALPHA, - - /// DOCME - Y4M_PIXFMT_MONO, + Y4M_PIXFMT_MONO, /// luma only (grayscale) }; - /// DOCME + /// Interlacing mode for an entire stream enum Y4M_InterlacingMode { + Y4M_ILACE_NOTSET = -1, /// undefined + Y4M_ILACE_PROGRESSIVE, /// progressive (no interlacing) - /// DOCME - Y4M_ILACE_NOTSET = -1, // not to be confused with Y4M_ILACE_UNKNOWN + Y4M_ILACE_TFF, /// interlaced, top field first + Y4M_ILACE_BFF, /// interlaced, bottom field first - /// DOCME - Y4M_ILACE_PROGRESSIVE, - - /// DOCME - Y4M_ILACE_TFF, - - /// DOCME - Y4M_ILACE_BFF, - - /// DOCME - Y4M_ILACE_MIXED, - - /// DOCME - Y4M_ILACE_UNKNOWN, + Y4M_ILACE_MIXED, /// mixed interlaced/progressive, possibly with RFF flags + Y4M_ILACE_UNKNOWN, /// unknown interlacing mode (not the same as undefined) }; - /// DOCME + /// Frame information flags enum Y4M_FrameFlags { + Y4M_FFLAG_NOTSET = -1, /// undefined + Y4M_FFLAG_NONE = 0x0000, /// no flags set - /// DOCME - Y4M_FFLAG_NOTSET = -1, + /// field order/repeat field flags + Y4M_FFLAG_R_TFF = 0x0001, /// top field first + Y4M_FFLAG_R_TFF_R = 0x0002, /// top field first, and repeat that field + Y4M_FFLAG_R_BFF = 0x0004, /// bottom field first + Y4M_FFLAG_R_BFF_R = 0x0008, /// bottom field first, and repeat that field + Y4M_FFLAG_R_P = 0x0010, /// progressive + Y4M_FFLAG_R_P_R = 0x0020, /// progressive, and repeat frame once + Y4M_FFLAG_R_P_RR = 0x0040, /// progressive, and repeat frame twice - /// DOCME - Y4M_FFLAG_NONE = 0x0000, + /// temporal sampling flags + Y4M_FFLAG_T_P = 0x0080, /// progressive (fields sampled at the same time) + Y4M_FFLAG_T_I = 0x0100, /// interlaced (fields sampled at different times) - /// DOCME - Y4M_FFLAG_R_TFF = 0x0001, // TFF - - /// DOCME - Y4M_FFLAG_R_TFF_R = 0x0002, // TFF and repeat - - /// DOCME - Y4M_FFLAG_R_BFF = 0x0004, // BFF - - /// DOCME - Y4M_FFLAG_R_BFF_R = 0x0008, // BFF and repeat - - /// DOCME - Y4M_FFLAG_R_P = 0x0010, // progressive - - /// DOCME - Y4M_FFLAG_R_P_R = 0x0020, // progressive and repeat once - - /// DOCME - Y4M_FFLAG_R_P_RR = 0x0040, // progressive and repeat twice - - /// DOCME - Y4M_FFLAG_T_P = 0x0080, // progressive (fields sampled at the same time) - - /// DOCME - Y4M_FFLAG_T_I = 0x0100, // interlaced (fields sampled at different times) - - /// DOCME - Y4M_FFLAG_C_P = 0x0200, // progressive (whole frame subsampled) - - /// DOCME - Y4M_FFLAG_C_I = 0x0400, // interlaced (fields subsampled independently) - - /// DOCME - Y4M_FFLAG_C_UNKNOWN = 0x0800, // unknown (only allowed for non-4:2:0 sampling) + /// chroma subsampling flags + Y4M_FFLAG_C_P = 0x0200, /// progressive (whole frame subsampled) + Y4M_FFLAG_C_I = 0x0400, /// interlaced (fields subsampled independently) + Y4M_FFLAG_C_UNKNOWN = 0x0800, /// unknown (only allowed for non-4:2:0 sampling) }; - /// DOCME - FILE *sf; // source file + FILE *sf; /// source file + bool inited; /// initialization state - /// DOCME - bool inited; + int w, h; /// frame width/height + int num_frames; /// length of file in frames + int frame_sz; /// size of each frame in bytes + int luma_sz; /// size of the luma plane of each frame, in bytes + int chroma_sz; /// size of one of the two chroma planes of each frame, in bytes + int cur_fn; /// current frame number - /// DOCME - - /// DOCME - int w, h; // width/height - - /// DOCME - int num_frames; // length of file in frames - - /// DOCME - int frame_sz; // size of each frame in bytes - - /// DOCME - Y4M_PixelFormat pixfmt; // colorspace/pixel format - - /// DOCME - Y4M_InterlacingMode imode; // interlacing mode + Y4M_PixelFormat pixfmt; /// colorspace/pixel format + Y4M_InterlacingMode imode; /// interlacing mode (for the entire stream) struct { + int num; /// numerator + int den; /// denominator + } fps_rat; /// framerate - /// DOCME - int num; + /// a list of byte positions detailing where in the file + /// each frame header can be found + std::vector seek_table; - /// DOCME - int den; - - /// DOCME - } fps_rat; // framerate - - - /// DOCME - std::vector seek_table; // the position in the file of each frame, in bytes - - /// DOCME - int cur_fn; // current frame number - - - /// DOCME - wxString errmsg; + wxString errmsg; /// error message void LoadVideo(const wxString filename); void Close(); @@ -224,33 +156,11 @@ public: int GetHeight(); double GetFPS(); - /// @brief DOCME - /// @return - /// bool AreKeyFramesLoaded() { return false; } - - /// @brief DOCME - /// @return - /// wxArrayInt GetKeyFrames() { return wxArrayInt(); } - - /// @brief DOCME - /// @return - /// bool IsVFR() { return false; }; - - /// @brief DOCME - /// @return - /// FrameRate GetTrueFrameRate() { return FrameRate(); } - - /// @brief DOCME - /// @return - /// wxString GetDecoderName() { return L"YUV4MPEG"; } - - /// @brief DOCME - /// int GetDesiredCacheSize() { return 8; } };