1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
8 //
9 //
10 // License Agreement
11 // For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2015, OpenCV Foundation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
21 //
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
25 //
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 #include "precomp.hpp"
43 #include "opencv2/videoio/container_avi.private.hpp"
44
45 namespace cv
46 {
47
48 class MotionJpegCapture: public IVideoCapture
49 {
50 public:
51 virtual ~MotionJpegCapture() CV_OVERRIDE;
52 virtual double getProperty(int) const CV_OVERRIDE;
53 virtual bool setProperty(int, double) CV_OVERRIDE;
54 virtual bool grabFrame() CV_OVERRIDE;
55 virtual bool retrieveFrame(int, OutputArray) CV_OVERRIDE;
56 virtual bool isOpened() const CV_OVERRIDE;
getCaptureDomain()57 virtual int getCaptureDomain() CV_OVERRIDE { return CAP_OPENCV_MJPEG; }
58 MotionJpegCapture(const String&);
59
60 bool open(const String&);
61 void close();
62 protected:
63
64 inline uint64_t getFramePos() const;
65
66 Ptr<AVIReadContainer> m_avi_container;
67 bool m_is_first_frame;
68 frame_list m_mjpeg_frames;
69
70 frame_iterator m_frame_iterator;
71 Mat m_current_frame;
72
73 //frame width/height and fps could be different for
74 //each frame/stream. At the moment we suppose that they
75 //stays the same within single avi file.
76 uint32_t m_frame_width;
77 uint32_t m_frame_height;
78 double m_fps;
79 };
80
getFramePos() const81 uint64_t MotionJpegCapture::getFramePos() const
82 {
83 if(m_is_first_frame)
84 return 0;
85
86 if(m_frame_iterator == m_mjpeg_frames.end())
87 return m_mjpeg_frames.size();
88
89 return m_frame_iterator - m_mjpeg_frames.begin() + 1;
90 }
91
setProperty(int property,double value)92 bool MotionJpegCapture::setProperty(int property, double value)
93 {
94 if(property == CAP_PROP_POS_FRAMES)
95 {
96 if(int(value) == 0)
97 {
98 m_is_first_frame = true;
99 m_frame_iterator = m_mjpeg_frames.end();
100 return true;
101 }
102 else if(m_mjpeg_frames.size() > value)
103 {
104 m_frame_iterator = m_mjpeg_frames.begin() + int(value - 1);
105 m_is_first_frame = false;
106 return true;
107 }
108 }
109
110 return false;
111 }
112
getProperty(int property) const113 double MotionJpegCapture::getProperty(int property) const
114 {
115 switch(property)
116 {
117 case CAP_PROP_POS_FRAMES:
118 return (double)getFramePos();
119 case CAP_PROP_POS_MSEC:
120 return (double)getFramePos() * (1000. / m_fps);
121 case CAP_PROP_POS_AVI_RATIO:
122 return double(getFramePos())/m_mjpeg_frames.size();
123 case CAP_PROP_FRAME_WIDTH:
124 return (double)m_frame_width;
125 case CAP_PROP_FRAME_HEIGHT:
126 return (double)m_frame_height;
127 case CAP_PROP_FPS:
128 return m_fps;
129 case CAP_PROP_FOURCC:
130 return (double)CV_FOURCC('M','J','P','G');
131 case CAP_PROP_FRAME_COUNT:
132 return (double)m_mjpeg_frames.size();
133 case CAP_PROP_FORMAT:
134 return 0;
135 default:
136 return 0;
137 }
138 }
139
grabFrame()140 bool MotionJpegCapture::grabFrame()
141 {
142 if(isOpened())
143 {
144 if(m_is_first_frame)
145 {
146 m_is_first_frame = false;
147 m_frame_iterator = m_mjpeg_frames.begin();
148 }
149 else
150 {
151 if (m_frame_iterator == m_mjpeg_frames.end())
152 return false;
153
154 ++m_frame_iterator;
155 }
156 }
157
158 return m_frame_iterator != m_mjpeg_frames.end();
159 }
160
retrieveFrame(int,OutputArray output_frame)161 bool MotionJpegCapture::retrieveFrame(int, OutputArray output_frame)
162 {
163 if(m_frame_iterator != m_mjpeg_frames.end())
164 {
165 std::vector<char> data = m_avi_container->readFrame(m_frame_iterator);
166
167 if(data.size())
168 {
169 m_current_frame = imdecode(data, IMREAD_ANYDEPTH | IMREAD_COLOR | IMREAD_IGNORE_ORIENTATION);
170 }
171
172 m_current_frame.copyTo(output_frame);
173
174 return true;
175 }
176
177 return false;
178 }
179
~MotionJpegCapture()180 MotionJpegCapture::~MotionJpegCapture()
181 {
182 close();
183 }
184
MotionJpegCapture(const String & filename)185 MotionJpegCapture::MotionJpegCapture(const String& filename)
186 {
187 m_avi_container = makePtr<AVIReadContainer>();
188 m_avi_container->initStream(filename);
189 open(filename);
190 }
191
isOpened() const192 bool MotionJpegCapture::isOpened() const
193 {
194 return m_mjpeg_frames.size() > 0;
195 }
196
close()197 void MotionJpegCapture::close()
198 {
199 m_avi_container->close();
200 m_frame_iterator = m_mjpeg_frames.end();
201 }
202
open(const String & filename)203 bool MotionJpegCapture::open(const String& filename)
204 {
205 close();
206
207 m_avi_container = makePtr<AVIReadContainer>();
208 m_avi_container->initStream(filename);
209
210 m_frame_iterator = m_mjpeg_frames.end();
211 m_is_first_frame = true;
212
213 if(!m_avi_container->parseRiff(m_mjpeg_frames))
214 {
215 close();
216 } else
217 {
218 m_frame_width = m_avi_container->getWidth();
219 m_frame_height = m_avi_container->getHeight();
220 m_fps = m_avi_container->getFps();
221 }
222
223 return isOpened();
224 }
225
createMotionJpegCapture(const String & filename)226 Ptr<IVideoCapture> createMotionJpegCapture(const String& filename)
227 {
228 Ptr<MotionJpegCapture> mjdecoder(new MotionJpegCapture(filename));
229 if( mjdecoder->isOpened() )
230 return mjdecoder;
231 return Ptr<MotionJpegCapture>();
232 }
233
234 }
235