2 * Copyright 2009, Stephan Aßmus <superstippi@gmx.de>
3 * Copyright 2014, Colin Günther <coling@gmx.de>
4 * All rights reserved. Distributed under the terms of the GNU L-GPL license.
10 /*! \brief This file contains functions to convert and calculate values from
11 FFmpeg to Media Kit and vice versa.
17 #include <GraphicsDefs.h>
24 /*! \brief Converts FFmpeg notation of video aspect ratio into the Media Kits
27 \see ConvertVideoAspectWidthAndHeightToAVCodecContext() for converting in
30 \param contextIn An AVCodeContext structure of FFmpeg containing the values
31 needed to calculate the Media Kit video aspect ratio.
32 The following fields are used for the calculation:
33 - AVCodecContext.sample_aspect_ratio.num (optional)
34 - AVCodecContext.sample_aspect_ratio.den (optional)
35 - AVCodecContext.width (must)
36 - AVCodecContext.height (must)
37 \param pixelWidthAspectOut On return contains Media Kits notation of the
38 video aspect ratio width. E.g. 16:9 -> 16 is returned here
39 \param pixelHeightAspectOut On return contains Media Kits notation of the
40 video aspect ratio height. E.g. 16:9 -> 9 is returned here
43 ConvertAVCodecContextToVideoAspectWidthAndHeight(AVCodecContext
& contextIn
,
44 uint16
& pixelWidthAspectOut
, uint16
& pixelHeightAspectOut
)
46 assert(contextIn
.sample_aspect_ratio
.num
>= 0);
47 assert(contextIn
.width
> 0);
48 assert(contextIn
.height
> 0);
50 // The following code is based on code originally located in
51 // AVFormatReader::Stream::Init() and thus should be copyrighted to Stephan
53 AVRational pixelAspectRatio
;
55 if (contextIn
.sample_aspect_ratio
.num
== 0
56 || contextIn
.sample_aspect_ratio
.den
== 0) {
57 // AVCodecContext doesn't contain a video aspect ratio, so calculate it
58 // ourselve based solely on the video dimensions
59 av_reduce(&pixelAspectRatio
.num
, &pixelAspectRatio
.den
, contextIn
.width
,
60 contextIn
.height
, 1024 * 1024);
62 pixelWidthAspectOut
= static_cast<int16
>(pixelAspectRatio
.num
);
63 pixelHeightAspectOut
= static_cast<int16
>(pixelAspectRatio
.den
);
67 // AVCodecContext contains a video aspect ratio, so use it
68 av_reduce(&pixelAspectRatio
.num
, &pixelAspectRatio
.den
,
69 contextIn
.width
* contextIn
.sample_aspect_ratio
.num
,
70 contextIn
.height
* contextIn
.sample_aspect_ratio
.den
,
73 pixelWidthAspectOut
= static_cast<int16
>(pixelAspectRatio
.num
);
74 pixelHeightAspectOut
= static_cast<int16
>(pixelAspectRatio
.den
);
78 /*! \brief Converts the Media Kits notation of video aspect ratio into FFmpegs
81 \see ConvertAVCodecContextToVideoAspectWidthAndHeight() for converting in
84 \param pixelWidthAspectIn Contains Media Kits notation of the video aspect
85 ratio width. E.g. 16:9 -> 16 is passed here.
86 \param pixelHeightAspectIn Contains Media Kits notation of the video aspect
87 ratio height. E.g. 16:9 -> 9 is passed here.
88 \param contextInOut An AVCodecContext structure of FFmpeg.
89 On input must contain the following fields already initialized
90 otherwise the behaviour is undefined:
91 - AVCodecContext.width (must)
92 - AVCodecContext.height (must)
93 On output contains converted values in the following fields (other
94 fields stay as they were on input):
95 - AVCodecContext.sample_aspect_ratio.num
96 - AVCodecContext.sample_aspect_ratio.den
99 ConvertVideoAspectWidthAndHeightToAVCodecContext(uint16 pixelWidthAspectIn
,
100 uint16 pixelHeightAspectIn
, AVCodecContext
& contextInOut
)
102 assert(pixelWidthAspectIn
> 0);
103 assert(pixelHeightAspectIn
> 0);
104 assert(contextInOut
.width
> 0);
105 assert(contextInOut
.height
> 0);
107 AVRational pureVideoDimensionAspectRatio
;
108 av_reduce(&pureVideoDimensionAspectRatio
.num
,
109 &pureVideoDimensionAspectRatio
.den
, contextInOut
.width
,
110 contextInOut
.height
, 1024 * 1024);
112 if (pureVideoDimensionAspectRatio
.num
== pixelWidthAspectIn
113 && pureVideoDimensionAspectRatio
.den
== pixelHeightAspectIn
) {
114 // The passed Media Kit pixel aspect ratio equals the video dimension
115 // aspect ratio. Set sample_aspect_ratio to "ignore".
116 contextInOut
.sample_aspect_ratio
.num
= 0;
117 contextInOut
.sample_aspect_ratio
.den
= 1;
121 av_reduce(&contextInOut
.sample_aspect_ratio
.num
,
122 &contextInOut
.sample_aspect_ratio
.den
,
123 contextInOut
.height
* pixelWidthAspectIn
,
124 contextInOut
.width
* pixelHeightAspectIn
,
129 /*! \brief Calculates bytes per row for a video frame.
131 \param colorSpace The Media Kit color space the video frame uses.
132 \param videoWidth The width of the video frame.
134 \returns bytes per video frame row
135 \returns Zero, when bytes per video frame cannot be calculated.
138 CalculateBytesPerRowWithColorSpaceAndVideoWidth(color_space colorSpace
, int videoWidth
)
140 assert(videoWidth
>= 0);
142 const uint32 kBytesPerRowUnknown
= 0;
143 size_t bytesPerPixel
;
146 if (get_pixel_size_for(colorSpace
, &bytesPerPixel
, &rowAlignment
, NULL
) != B_OK
)
147 return kBytesPerRowUnknown
;
149 uint32 bytesPerRow
= bytesPerPixel
* videoWidth
;
150 uint32 numberOfUnalignedBytes
= bytesPerRow
% rowAlignment
;
152 if (numberOfUnalignedBytes
== 0)
155 uint32 numberOfBytesNeededForAlignment
= rowAlignment
- numberOfUnalignedBytes
;
156 bytesPerRow
+= numberOfBytesNeededForAlignment
;
162 /*! \brief Converts FFmpeg notation of video frame rate into the Media Kits
165 \see ConvertAVCodecContextToVideoFrameRate() for converting in the other
168 \param contextIn An AVCodeContext structure of FFmpeg containing the values
169 needed to calculate the Media Kit video frame rate.
170 The following fields are used for the calculation:
171 - AVCodecContext.time_base.num (must)
172 - AVCodecContext.time_base.den (must)
173 - AVCodecContext.ticks_per_frame (must)
174 \param frameRateOut On return contains Media Kits notation of the video
178 ConvertAVCodecContextToVideoFrameRate(AVCodecContext
& contextIn
, float& frameRateOut
)
180 // assert that av_q2d(contextIn.time_base) > 0 and computable
181 assert(contextIn
.time_base
.num
> 0);
182 assert(contextIn
.time_base
.den
> 0);
184 // The following code is based on private get_fps() function of FFmpeg's
186 // https://lists.ffmpeg.org/pipermail/ffmpeg-cvslog/2012-April/049280.html
187 double possiblyInterlacedFrameRate
= 1.0 / av_q2d(contextIn
.time_base
);
188 double numberOfInterlacedFramesPerFullFrame
= FFMAX(contextIn
.ticks_per_frame
, 1);
191 = possiblyInterlacedFrameRate
/ numberOfInterlacedFramesPerFullFrame
;
195 /*! \brief Converts the Media Kits notation of video frame rate to FFmpegs
198 \see ConvertAVCodecContextToVideoFrameRate() for converting in the other
201 \param frameRateIn Contains Media Kits notation of the video frame rate
202 that will be converted into FFmpegs notation. Must be greater than
204 \param contextOut An AVCodecContext structure of FFmpeg.
205 On output contains converted values in the following fields (other
206 fields stay as they were on input):
207 - AVCodecContext.time_base.num
208 - AVCodecContext.time_base.den
209 - AVCodecContext.ticks_per_frame is set to 1
212 ConvertVideoFrameRateToAVCodecContext(float frameRateIn
,
213 AVCodecContext
& contextOut
)
215 assert(frameRateIn
> 0);
217 contextOut
.ticks_per_frame
= 1;
218 contextOut
.time_base
= av_d2q(1.0 / frameRateIn
, 1024);
222 /*! \brief Converts the Media Kits notation of an audio sample format to
225 \see ConvertAVSampleFormatToRawAudioFormat() for converting in the other
228 \param rawAudioFormatIn Contains Media Kits notation of an audio sample
229 format that will be converted into FFmpegs notation.
230 \param sampleFormatOut On output contains FFmpegs notation of the passed
231 audio sample format. Might return AV_SAMPLE_FMT_NONE if there is no
235 ConvertRawAudioFormatToAVSampleFormat(uint32 rawAudioFormatIn
,
236 AVSampleFormat
& sampleFormatOut
)
238 switch (rawAudioFormatIn
) {
239 case media_raw_audio_format::B_AUDIO_FLOAT
:
240 sampleFormatOut
= AV_SAMPLE_FMT_FLT
;
243 case media_raw_audio_format::B_AUDIO_DOUBLE
:
244 sampleFormatOut
= AV_SAMPLE_FMT_DBL
;
247 case media_raw_audio_format::B_AUDIO_INT
:
248 sampleFormatOut
= AV_SAMPLE_FMT_S32
;
251 case media_raw_audio_format::B_AUDIO_SHORT
:
252 sampleFormatOut
= AV_SAMPLE_FMT_S16
;
255 case media_raw_audio_format::B_AUDIO_UCHAR
:
256 sampleFormatOut
= AV_SAMPLE_FMT_U8
;
260 // Silence compiler warnings about unhandled enumeration values.
264 sampleFormatOut
= AV_SAMPLE_FMT_NONE
;
268 /*! \brief Converts FFmpegs notation of an audio sample format to the Media
271 \see ConvertAVSampleFormatToRawAudioFormat() for converting in the other
274 \param sampleFormatIn Contains FFmpegs notation of an audio sample format
275 that will be converted into the Media Kits notation.
276 \param rawAudioFormatOut On output contains Media Kits notation of the
277 passed audio sample format. Might return 0 if there is no conversion
281 ConvertAVSampleFormatToRawAudioFormat(AVSampleFormat sampleFormatIn
,
282 uint32
& rawAudioFormatOut
)
284 switch (sampleFormatIn
) {
285 case AV_SAMPLE_FMT_FLT
:
286 case AV_SAMPLE_FMT_FLTP
:
287 rawAudioFormatOut
= media_raw_audio_format::B_AUDIO_FLOAT
;
290 case AV_SAMPLE_FMT_DBL
:
291 case AV_SAMPLE_FMT_DBLP
:
292 rawAudioFormatOut
= media_raw_audio_format::B_AUDIO_DOUBLE
;
295 case AV_SAMPLE_FMT_S32
:
296 case AV_SAMPLE_FMT_S32P
:
297 rawAudioFormatOut
= media_raw_audio_format::B_AUDIO_INT
;
300 case AV_SAMPLE_FMT_S16
:
301 case AV_SAMPLE_FMT_S16P
:
302 rawAudioFormatOut
= media_raw_audio_format::B_AUDIO_SHORT
;
305 case AV_SAMPLE_FMT_U8
:
306 case AV_SAMPLE_FMT_U8P
:
307 rawAudioFormatOut
= media_raw_audio_format::B_AUDIO_UCHAR
;
311 // Silence compiler warnings about unhandled enumeration values.
315 const uint32 kBAudioNone
= 0;
316 rawAudioFormatOut
= kBAudioNone
;
320 #endif // UTILITIES_H