// of this distribution and at http://opencv.org/license.html.
#include "opencv2/videoio/container_avi.private.hpp"
+#include <fstream>
+#include <limits>
+#include <typeinfo>
namespace cv
{
+// Utility function for safe integer conversions
+template <typename D, typename S>
+inline D safe_int_cast(S val)
+{
+ typedef std::numeric_limits<S> st;
+ typedef std::numeric_limits<D> dt;
+ CV_StaticAssert(st::is_integer && dt::is_integer, "Integer type is expected");
+ const bool in_range_r = (double)val <= (double)dt::max();
+ const bool in_range_l = (double)val >= (double)dt::min();
+ if (!in_range_r || !in_range_l)
+ {
+ CV_Error_(cv::Error::StsOutOfRange, ("Can not convert integer values (%s -> %s), value 0x%llx is out of range", typeid(S).name(), typeid(D).name(), val));
+ }
+ return static_cast<D>(val);
+}
+
const uint32_t RIFF_CC = CV_FOURCC('R','I','F','F');
const uint32_t LIST_CC = CV_FOURCC('L','I','S','T');
const uint32_t HDRL_CC = CV_FOURCC('h','d','r','l');
bool open(const String& filename);
void close();
operator bool();
- VideoInputStream& operator=(const VideoInputStream& stream);
private:
+ VideoInputStream(const VideoInputStream&);
+ VideoInputStream& operator=(const VideoInputStream&);
+
+private:
+ std::ifstream input;
bool m_is_valid;
String m_fname;
- FILE* m_f;
};
#pragma pack(pop)
return format("%c%c%c%c", fourcc & 255, (fourcc >> 8) & 255, (fourcc >> 16) & 255, (fourcc >> 24) & 255);
}
-VideoInputStream::VideoInputStream(): m_is_valid(false), m_f(0)
+VideoInputStream::VideoInputStream(): m_is_valid(false)
{
m_fname = String();
}
-VideoInputStream::VideoInputStream(const String& filename): m_is_valid(false), m_f(0)
+VideoInputStream::VideoInputStream(const String& filename): m_is_valid(false)
{
m_fname = filename;
open(filename);
bool VideoInputStream::isOpened() const
{
- return m_f != 0;
+ return input.is_open();
}
bool VideoInputStream::open(const String& filename)
{
close();
-
- m_f = fopen(filename.c_str(), "rb");
-
+ input.open(filename.c_str(), std::ios_base::binary);
m_is_valid = isOpened();
-
return m_is_valid;
}
if(isOpened())
{
m_is_valid = false;
-
- fclose(m_f);
- m_f = 0;
+ input.close();
}
}
{
if(isOpened())
{
- m_is_valid = (count == fread((void*)buf, 1, (size_t)count, m_f));
+ input.read(buf, safe_int_cast<std::streamsize>(count));
+ m_is_valid = (input.gcount() == (std::streamsize)count);
}
return *this;
VideoInputStream& VideoInputStream::seekg(uint64_t pos)
{
- m_is_valid = (fseek(m_f, (int32_t)pos, SEEK_SET) == 0);
-
+ input.clear();
+ input.seekg(safe_int_cast<std::streamoff>(pos));
+ m_is_valid = !input.eof();
return *this;
}
uint64_t VideoInputStream::tellg()
{
- return ftell(m_f);
+ return input.tellg();
}
VideoInputStream::operator bool()
return m_is_valid;
}
-VideoInputStream& VideoInputStream::operator=(const VideoInputStream& stream)
-{
- if (this != &stream) {
- m_fname = stream.m_fname;
- // m_f = stream.m_f;
- open(m_fname);
- }
- return *this;
-}
-
VideoInputStream::~VideoInputStream()
{
close();
~BitStream() { close(); }
bool open(const String& filename);
- bool isOpened() const { return m_f != 0; }
+ bool isOpened() const { return output.is_open(); }
void close();
void writeBlock();
void putBytes(const uchar* buf, int count);
void putShort(int val);
- void putInt(int val);
+ void putInt(uint32_t val);
void jputShort(int val);
- void patchInt(int val, size_t pos);
+ void patchInt(uint32_t val, size_t pos);
void jput(unsigned currval);
void jflush(unsigned currval, int bitIdx);
+private:
+ BitStream(const BitStream &);
+ BitStream &operator=(const BitStream&);
+
protected:
+ std::ofstream output;
std::vector<uchar> m_buf;
uchar* m_start;
uchar* m_end;
uchar* m_current;
size_t m_pos;
bool m_is_opened;
- FILE* m_f;
};
static const size_t DEFAULT_BLOCK_SIZE = (1 << 15);
m_start = &m_buf[0];
m_end = m_start + DEFAULT_BLOCK_SIZE;
m_is_opened = false;
- m_f = 0;
m_current = 0;
m_pos = 0;
}
bool BitStream::open(const String& filename)
{
close();
- m_f = fopen(filename.c_str(), "wb");
- if( !m_f )
- return false;
+ output.open(filename.c_str(), std::ios_base::binary);
m_current = m_start;
m_pos = 0;
return true;
void BitStream::close()
{
writeBlock();
- if( m_f )
- fclose(m_f);
- m_f = 0;
+ output.close();
}
void BitStream::writeBlock()
{
- size_t wsz0 = m_current - m_start;
- if( wsz0 > 0 && m_f )
+ ptrdiff_t wsz0 = m_current - m_start;
+ if( wsz0 > 0 )
{
- size_t wsz = fwrite(m_start, 1, wsz0, m_f);
- CV_Assert( wsz == wsz0 );
+ output.write((char*)m_start, wsz0);
}
m_pos += wsz0;
m_current = m_start;
}
size_t BitStream::getPos() const {
- return (size_t)(m_current - m_start) + m_pos;
+ return safe_int_cast<size_t>(m_current - m_start) + m_pos;
}
void BitStream::putByte(int val)
void BitStream::putBytes(const uchar* buf, int count)
{
uchar* data = (uchar*)buf;
- CV_Assert(m_f && data && m_current && count >= 0);
+ CV_Assert(data && m_current && count >= 0);
if( m_current >= m_end )
writeBlock();
writeBlock();
}
-void BitStream::putInt(int val)
+void BitStream::putInt(uint32_t val)
{
m_current[0] = (uchar)val;
m_current[1] = (uchar)(val >> 8);
writeBlock();
}
-void BitStream::patchInt(int val, size_t pos)
+void BitStream::patchInt(uint32_t val, size_t pos)
{
if( pos >= m_pos )
{
- ptrdiff_t delta = pos - m_pos;
+ ptrdiff_t delta = safe_int_cast<ptrdiff_t>(pos - m_pos);
CV_Assert( delta < m_current - m_start );
m_start[delta] = (uchar)val;
m_start[delta+1] = (uchar)(val >> 8);
}
else
{
- CV_Assert(pos < (1u<<31));
- long fpos = ftell(m_f);
- fseek(m_f, (long)pos, SEEK_SET);
+ std::streamoff fpos = output.tellp();
+ output.seekp(safe_int_cast<std::streamoff>(pos));
uchar buf[] = { (uchar)val, (uchar)(val >> 8), (uchar)(val >> 16), (uchar)(val >> 24) };
- fwrite(buf, 1, 4, m_f);
- fseek(m_f, fpos, SEEK_SET);
+ output.write((char *)buf, 4);
+ output.seekp(fpos);
}
}
strm->putInt(0);
strm->putInt(SUG_BUFFER_SIZE);
- strm->putInt(AVI_DWQUALITY);
+ strm->putInt(static_cast<uint32_t>(AVI_DWQUALITY));
strm->putInt(0);
strm->putShort(0);
strm->putShort(0);
strm->putInt(MOVI_CC);
}
-void AVIWriteContainer::startWriteChunk(int fourcc)
+void AVIWriteContainer::startWriteChunk(uint32_t fourcc)
{
CV_Assert(fourcc != 0);
strm->putInt(fourcc);
if( !AVIChunkSizeIndex.empty() )
{
size_t currpos = strm->getPos();
+ CV_Assert(currpos > 4);
+ currpos -= 4;
size_t pospos = AVIChunkSizeIndex.back();
AVIChunkSizeIndex.pop_back();
- int chunksz = (int)(currpos - (pospos + 4));
+ CV_Assert(currpos >= pospos);
+ uint32_t chunksz = safe_int_cast<uint32_t>(currpos - pospos);
strm->patchInt(chunksz, pospos);
}
}
case dc: return CV_FOURCC(strm_indx[0], strm_indx[1], 'd', 'c');
case pc: return CV_FOURCC(strm_indx[0], strm_indx[1], 'p', 'c');
case wb: return CV_FOURCC(strm_indx[0], strm_indx[1], 'w', 'b');
- default: return CV_FOURCC(strm_indx[0], strm_indx[1], 'd', 'b');
}
+ return CV_FOURCC(strm_indx[0], strm_indx[1], 'd', 'b');
}
void AVIWriteContainer::writeIndex(int stream_number, StreamType strm_type)
void AVIWriteContainer::finishWriteAVI()
{
- int nframes = (int)frameOffset.size();
+ uint32_t nframes = safe_int_cast<uint32_t>(frameOffset.size());
// Record frames numbers to AVI Header
while (!frameNumIndexes.empty())
{