3641fb40affda48f8aab11b5c9398bdb896634c6
[occt.git] / src / Media / Media_Frame.cxx
1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2019 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 // activate some C99 macros like UINT64_C in "stdint.h" which used by FFmpeg
16 #ifndef __STDC_CONSTANT_MACROS
17   #define __STDC_CONSTANT_MACROS
18 #endif
19
20 #include <Media_Frame.hxx>
21
22 #include <Media_Scaler.hxx>
23
24 #ifdef HAVE_FFMPEG
25 #include <Standard_WarningsDisable.hxx>
26 extern "C"
27 {
28   #include <libavcodec/avcodec.h>
29   #include <libavutil/imgutils.h>
30 };
31 #include <Standard_WarningsRestore.hxx>
32 #endif
33
34 IMPLEMENT_STANDARD_RTTIEXT(Media_Frame, Standard_Transient)
35
36 // =======================================================================
37 // function : FormatFFmpeg2Occt
38 // purpose  :
39 // =======================================================================
40 Image_Format Media_Frame::FormatFFmpeg2Occt (int theFormat)
41 {
42 #ifdef HAVE_FFMPEG
43   switch (theFormat)
44   {
45     case AV_PIX_FMT_RGBA:
46       return Image_Format_RGBA;
47     case AV_PIX_FMT_BGRA:
48       return Image_Format_BGRA;
49     case AV_PIX_FMT_RGB0:
50       return Image_Format_RGB32;
51     case AV_PIX_FMT_BGR0:
52       return Image_Format_BGR32;
53     case AV_PIX_FMT_RGB24:
54       return Image_Format_RGB;
55     case AV_PIX_FMT_BGR24:
56       return Image_Format_BGR;
57     case AV_PIX_FMT_GRAY8:
58       return Image_Format_Gray;
59     default:
60       return Image_Format_UNKNOWN;
61   }
62 #else
63   (void )theFormat;
64   return Image_Format_UNKNOWN;
65 #endif
66 }
67
68 // =======================================================================
69 // function : FormatOcct2FFmpeg
70 // purpose  :
71 // =======================================================================
72 int Media_Frame::FormatOcct2FFmpeg (Image_Format theFormat)
73 {
74 #ifdef HAVE_FFMPEG
75   switch (theFormat)
76   {
77     case Image_Format_RGBA:
78       return AV_PIX_FMT_RGBA;
79     case Image_Format_BGRA:
80       return AV_PIX_FMT_BGRA;
81     case Image_Format_RGB32:
82       return AV_PIX_FMT_RGB0;
83     case Image_Format_BGR32:
84       return AV_PIX_FMT_BGR0;
85     case Image_Format_RGB:
86       return AV_PIX_FMT_RGB24;
87     case Image_Format_BGR:
88       return AV_PIX_FMT_BGR24;
89     case Image_Format_Gray:
90       return AV_PIX_FMT_GRAY8;
91     case Image_Format_Alpha:
92       return AV_PIX_FMT_GRAY8;
93     case Image_Format_GrayF:
94     case Image_Format_AlphaF:
95     case Image_Format_RGBAF:
96     case Image_Format_RGBF:
97     case Image_Format_BGRAF:
98     case Image_Format_BGRF:
99     case Image_Format_UNKNOWN:
100       return AV_PIX_FMT_NONE; // unsupported
101   }
102   return AV_PIX_FMT_NONE;
103 #else
104   (void )theFormat;
105   return 0;
106 #endif
107 }
108
109 // =======================================================================
110 // function : Media_Frame
111 // purpose  :
112 // =======================================================================
113 Media_Frame::Media_Frame()
114 : myFrame (NULL),
115   myFramePts  (0.0),
116   myPixelRatio(1.0f),
117   myIsLocked  (false)
118 {
119 #ifdef HAVE_FFMPEG
120   myFrame = av_frame_alloc();
121 #endif
122   Unref();
123 }
124
125 // =======================================================================
126 // function : ~Media_Frame
127 // purpose  :
128 // =======================================================================
129 Media_Frame::~Media_Frame()
130 {
131 #ifdef HAVE_FFMPEG
132   av_frame_free (&myFrame);
133 #endif
134 }
135
136 // =======================================================================
137 // function : Unref
138 // purpose  :
139 // =======================================================================
140 void Media_Frame::Unref()
141 {
142 #ifdef HAVE_FFMPEG
143   av_frame_unref (myFrame);
144 #endif
145 }
146
147 // =======================================================================
148 // function : IsFullRangeYUV
149 // purpose  :
150 // =======================================================================
151 bool Media_Frame::IsFullRangeYUV() const
152 {
153 #ifdef HAVE_FFMPEG
154   return Format() == AV_PIX_FMT_YUVJ420P
155       || myFrame->color_range == AVCOL_RANGE_JPEG;
156 #else
157   return true;
158 #endif
159 }
160
161 // =======================================================================
162 // function : Swap
163 // purpose  :
164 // =======================================================================
165 void Media_Frame::Swap (const Handle(Media_Frame)& theFrame1,
166                         const Handle(Media_Frame)& theFrame2)
167 {
168   std::swap (theFrame1->myFrame, theFrame2->myFrame);
169 }
170
171 // =======================================================================
172 // function : IsEmpty
173 // purpose  :
174 // =======================================================================
175 bool Media_Frame::IsEmpty() const
176 {
177 #ifdef HAVE_FFMPEG
178   return myFrame->format == -1; // AV_PIX_FMT_NONE
179 #else
180   return true;
181 #endif
182 }
183
184 // =======================================================================
185 // function : SizeX
186 // purpose  :
187 // =======================================================================
188 int Media_Frame::SizeX() const
189 {
190 #ifdef HAVE_FFMPEG
191   return myFrame->width;
192 #else
193   return 0;
194 #endif
195 }
196
197 // =======================================================================
198 // function : SizeY
199 // purpose  :
200 // =======================================================================
201 int Media_Frame::SizeY() const
202 {
203 #ifdef HAVE_FFMPEG
204   return myFrame->height;
205 #else
206   return 0;
207 #endif
208 }
209
210 // =======================================================================
211 // function : Format
212 // purpose  :
213 // =======================================================================
214 int Media_Frame::Format() const
215 {
216 #ifdef HAVE_FFMPEG
217   return myFrame->format;
218 #else
219   return 0;
220 #endif
221 }
222
223 // =======================================================================
224 // function : Plane
225 // purpose  :
226 // =======================================================================
227 uint8_t* Media_Frame::Plane (int thePlaneId) const
228 {
229 #ifdef HAVE_FFMPEG
230   return myFrame->data[thePlaneId];
231 #else
232   (void )thePlaneId;
233   return NULL;
234 #endif
235 }
236
237 // =======================================================================
238 // function : LineSize
239 // purpose  :
240 // =======================================================================
241 int Media_Frame::LineSize (int thePlaneId) const
242 {
243 #ifdef HAVE_FFMPEG
244   return myFrame->linesize[thePlaneId];
245 #else
246   (void )thePlaneId;
247   return 0;
248 #endif
249 }
250
251 // =======================================================================
252 // function : BestEffortTimestamp
253 // purpose  :
254 // =======================================================================
255 int64_t Media_Frame::BestEffortTimestamp() const
256 {
257 #ifdef HAVE_FFMPEG
258   return myFrame->best_effort_timestamp;
259 #else
260   return 0;
261 #endif
262 }
263
264 // =======================================================================
265 // function : InitWrapper
266 // purpose  :
267 // =======================================================================
268 bool Media_Frame::InitWrapper (const Handle(Image_PixMap)& thePixMap)
269 {
270   Unref();
271   if (thePixMap.IsNull())
272   {
273     return false;
274   }
275
276 #ifdef HAVE_FFMPEG
277   myFrame->format = FormatOcct2FFmpeg (thePixMap->Format());
278   if (myFrame->format == AV_PIX_FMT_NONE)
279   {
280     return false;
281   }
282
283   myFrame->width       = (int )thePixMap->SizeX();
284   myFrame->height      = (int )thePixMap->SizeY();
285   myFrame->data[0]     = (uint8_t* )thePixMap->ChangeData();
286   myFrame->linesize[0] = (int      )thePixMap->SizeRowBytes();
287   for (int aPlaneIter = 1; aPlaneIter < AV_NUM_DATA_POINTERS; ++aPlaneIter)
288   {
289     myFrame->data    [aPlaneIter] = NULL;
290     myFrame->linesize[aPlaneIter] = 0;
291   }
292   return true;
293 #else
294   return false;
295 #endif
296 }