1 /*
2 * pvidfile.cxx
3 *
4 * Video file implementation
5 *
6 * Portable Windows Library
7 *
8 * Copyright (C) 2004 Post Increment
9 *
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
14 *
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * The Original Code is Portable Windows Library.
21 *
22 * The Initial Developer of the Original Code is
23 * Craig Southeren <craigs@postincrement.com>
24 *
25 * All Rights Reserved.
26 *
27 * Contributor(s): ______________________________________.
28 *
29 * $Revision: 26686 $
30 * $Author: rjongbloed $
31 * $Date: 2011-11-23 20:22:20 -0600 (Wed, 23 Nov 2011) $
32 */
33
34 #ifdef __GNUC__
35 #pragma implementation "pvidfile.h"
36 #endif
37
38 #include <ptlib.h>
39
40 #if P_VIDEO
41 #if P_VIDFILE
42
43 #include <ptclib/pvidfile.h>
44 #include <ptlib/videoio.h>
45
46
47 ///////////////////////////////////////////////////////////////////////////////
48
PVideoFile()49 PVideoFile::PVideoFile()
50 : m_fixedFrameSize(false)
51 , m_fixedFrameRate(false)
52 , m_frameBytes(CalculateFrameBytes())
53 , m_headerOffset(0)
54 {
55 }
56
57
Open(const PFilePath & name,PFile::OpenMode mode,int opts)58 PBoolean PVideoFile::Open(const PFilePath & name, PFile::OpenMode mode, int opts)
59 {
60 static PRegularExpression res("_(sqcif|qcif|cif|cif4|cif16|[0-9]+x[0-9]+)[^a-z0-9]", PRegularExpression::Extended|PRegularExpression::IgnoreCase);
61 static PRegularExpression fps("_[0-9]+fps[^a-z]", PRegularExpression::Extended|PRegularExpression::IgnoreCase);
62
63 PINDEX pos, len;
64
65 if (name.FindRegEx(res, pos, len)) {
66 m_fixedFrameSize = Parse(name.Mid(pos+1, len-2));
67 if (m_fixedFrameSize)
68 m_frameBytes = CalculateFrameBytes();
69 }
70
71 if ((pos = name.FindRegEx(fps)) != P_MAX_INDEX)
72 m_fixedFrameRate = PVideoFrameInfo::SetFrameRate(name.Mid(pos+1).AsUnsigned());
73
74 return m_file.Open(name, mode, opts);
75 }
76
77
WriteFrame(const void * frame)78 PBoolean PVideoFile::WriteFrame(const void * frame)
79 {
80 return m_file.Write(frame, m_frameBytes);
81 }
82
83
ReadFrame(void * frame)84 PBoolean PVideoFile::ReadFrame(void * frame)
85 {
86 if (m_file.Read(frame, m_frameBytes) && m_file.GetLastReadCount() == m_frameBytes)
87 return true;
88
89 #if PTRACING
90 if (m_file.GetErrorCode(PFile::LastReadError) != PFile::NoError)
91 PTRACE(2, "VidFile\tError reading file \"" << m_file.GetFilePath()
92 << "\" - " << m_file.GetErrorText(PFile::LastReadError));
93 else
94 PTRACE(4, "VidFile\tEnd of file \"" << m_file.GetFilePath() << '"');
95 #endif
96 return false;
97 }
98
99
GetLength() const100 off_t PVideoFile::GetLength() const
101 {
102 off_t len = m_file.GetLength();
103 return len < m_headerOffset ? 0 : ((len - m_headerOffset)/m_frameBytes);
104 }
105
106
SetLength(off_t len)107 PBoolean PVideoFile::SetLength(off_t len)
108 {
109 return m_file.SetLength(len*m_frameBytes + m_headerOffset);
110 }
111
112
GetPosition() const113 off_t PVideoFile::GetPosition() const
114 {
115 off_t pos = m_file.GetPosition();
116 return pos < m_headerOffset ? 0 : ((pos - m_headerOffset)/m_frameBytes);
117 }
118
119
SetPosition(off_t pos,PFile::FilePositionOrigin origin)120 PBoolean PVideoFile::SetPosition(off_t pos, PFile::FilePositionOrigin origin)
121 {
122 pos *= m_frameBytes;
123 if (origin == PFile::Start)
124 pos += m_headerOffset;
125
126 return m_file.SetPosition(pos, origin);
127 }
128
129
SetFrameSize(unsigned width,unsigned height)130 PBoolean PVideoFile::SetFrameSize(unsigned width, unsigned height)
131 {
132 if (frameWidth == width && frameHeight == height)
133 return true;
134
135 if (m_fixedFrameSize)
136 return false;
137
138 if (!PVideoFrameInfo::SetFrameSize(width, height))
139 return false;
140
141 m_frameBytes = CalculateFrameBytes();
142 return m_frameBytes > 0;
143 }
144
145
SetFrameRate(unsigned rate)146 PBoolean PVideoFile::SetFrameRate(unsigned rate)
147 {
148 if (frameRate == rate)
149 return true;
150
151 if (m_fixedFrameRate)
152 return false;
153
154 return PVideoFrameInfo::SetFrameRate(rate);
155 }
156
157
158
159 ///////////////////////////////////////////////////////////////////////////////
160
161 PFACTORY_CREATE(PFactory<PVideoFile>, PYUVFile, "yuv", false);
162 static PFactory<PVideoFile>::Worker<PYUVFile> y4mFileFactory("y4m");
163
164
PYUVFile()165 PYUVFile::PYUVFile()
166 : m_y4mMode(false)
167 {
168 }
169
170
Open(const PFilePath & name,PFile::OpenMode mode,int opts)171 PBoolean PYUVFile::Open(const PFilePath & name, PFile::OpenMode mode, int opts)
172 {
173 if (!PVideoFile::Open(name, mode, opts))
174 return false;
175
176 m_y4mMode = name.GetType() *= ".y4m";
177
178 if (m_y4mMode) {
179 int ch;
180 do {
181 if ((ch = m_file.ReadChar()) < 0)
182 return false;
183 }
184 while (ch != '\n');
185 m_headerOffset = m_file.GetPosition();
186 }
187
188 return true;
189 }
190
191
WriteFrame(const void * frame)192 PBoolean PYUVFile::WriteFrame(const void * frame)
193 {
194 if (m_y4mMode)
195 m_file.WriteChar('\n');
196
197 return m_file.Write(frame, m_frameBytes);
198 }
199
200
ReadFrame(void * frame)201 PBoolean PYUVFile::ReadFrame(void * frame)
202 {
203 if (m_y4mMode) {
204 PString info;
205 info.ReadFrom(m_file);
206 PTRACE(4, "VidFile\ty4m \"" << info << '"');
207 }
208
209 return PVideoFile::ReadFrame(frame);
210 }
211
212
213 #endif // P_VIDFILE
214 #endif // P_VIDEO
215