1 /* 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. 5 */ 6 #ifndef UTILITIES_H 7 #define UTILITIES_H 8 9 10 /*! \brief This file contains functions to convert and calculate values from 11 FFmpeg to Media Kit and vice versa. 12 */ 13 14 15 #include <assert.h> 16 17 #include <GraphicsDefs.h> 18 19 extern "C" { 20 #include "avcodec.h" 21 } 22 23 24 /*! \brief Converts FFmpeg notation of video aspect ratio into the Media Kits 25 notation. 26 27 \param contextIn An AVCodeContext structure of FFmpeg containing the values 28 needed to calculate the Media Kit video aspect ratio. 29 The following fields are used for the calculation: 30 - AVCodecContext.sample_aspect_ratio.num (optional) 31 - AVCodecContext.sample_aspect_ratio.den (optional) 32 - AVCodecContext.width (must) 33 - AVCodecContext.height (must) 34 \param pixelWidthAspectOut On return contains Media Kits notation of the 35 video aspect ratio width. E.g. 16:9 -> 16 is returned here 36 \param pixelHeightAspectOut On return contains Media Kits notation of the 37 video aspect ratio height. E.g. 16:9 -> 9 is returned here 38 */ 39 inline void 40 ConvertAVCodecContextToVideoAspectWidthAndHeight(AVCodecContext& contextIn, 41 uint16& pixelWidthAspectOut, uint16& pixelHeightAspectOut) 42 { 43 assert(contextIn.sample_aspect_ratio.num >= 0); 44 assert(contextIn.sample_aspect_ratio.den > 0); 45 assert(contextIn.width > 0); 46 assert(contextIn.height > 0); 47 48 // The following code is based on code originally located in 49 // AVFormatReader::Stream::Init() and thus should be copyrighted to Stephan 50 // Aßmus 51 AVRational pixelAspectRatio; 52 53 if (contextIn.sample_aspect_ratio.num == 0) { 54 // AVCodecContext doesn't contain a video aspect ratio, so calculate it 55 // ourselve based solely on the video dimensions 56 av_reduce(&pixelAspectRatio.num, &pixelAspectRatio.den, contextIn.width, 57 contextIn.height, 1024 * 1024); 58 59 pixelWidthAspectOut = static_cast<int16>(pixelAspectRatio.num); 60 pixelHeightAspectOut = static_cast<int16>(pixelAspectRatio.den); 61 return; 62 } 63 64 // AVCodecContext contains a video aspect ratio, so use it 65 av_reduce(&pixelAspectRatio.num, &pixelAspectRatio.den, 66 contextIn.width * contextIn.sample_aspect_ratio.num, 67 contextIn.height * contextIn.sample_aspect_ratio.den, 68 1024 * 1024); 69 70 pixelWidthAspectOut = static_cast<int16>(pixelAspectRatio.num); 71 pixelHeightAspectOut = static_cast<int16>(pixelAspectRatio.den); 72 } 73 74 75 /*! \brief Calculates bytes per row for a video frame. 76 77 \param colorSpace The Media Kit color space the video frame uses. 78 \param videoWidth The width of the video frame. 79 80 \returns bytes per video frame row 81 \returns Zero, when bytes per video frame cannot be calculated. 82 */ 83 inline uint32 84 CalculateBytesPerRowWithColorSpaceAndVideoWidth(color_space colorSpace, int videoWidth) 85 { 86 assert(videoWidth >= 0); 87 88 const uint32 kBytesPerRowUnknown = 0; 89 size_t bytesPerPixel; 90 size_t rowAlignment; 91 92 if (get_pixel_size_for(colorSpace, &bytesPerPixel, &rowAlignment, NULL) != B_OK) 93 return kBytesPerRowUnknown; 94 95 uint32 bytesPerRow = bytesPerPixel * videoWidth; 96 uint32 numberOfUnalignedBytes = bytesPerRow % rowAlignment; 97 98 if (numberOfUnalignedBytes == 0) 99 return bytesPerRow; 100 101 uint32 numberOfBytesNeededForAlignment = rowAlignment - numberOfUnalignedBytes; 102 bytesPerRow += numberOfBytesNeededForAlignment; 103 104 return bytesPerRow; 105 } 106 107 108 /*! \brief Converts FFmpeg notation of video frame rate into the Media Kits 109 notation. 110 111 \param contextIn An AVCodeContext structure of FFmpeg containing the values 112 needed to calculate the Media Kit video frame rate. 113 The following fields are used for the calculation: 114 - AVCodecContext.time_base.num (must) 115 - AVCodecContext.time_base.den (must) 116 - AVCodecContext.ticks_per_frame (must) 117 \param frameRateOut On return contains Media Kits notation of the video 118 frame rate. 119 */ 120 inline void 121 ConvertAVCodecContextToVideoFrameRate(AVCodecContext& contextIn, float& frameRateOut) 122 { 123 // assert that av_q2d(contextIn.time_base) > 0 and computable 124 assert(contextIn.time_base.num > 0); 125 assert(contextIn.time_base.den > 0); 126 127 // The following code is based on private get_fps() function of FFmpeg's 128 // ratecontrol.c: 129 // https://lists.ffmpeg.org/pipermail/ffmpeg-cvslog/2012-April/049280.html 130 double possiblyInterlacedFrameRate = 1.0 / av_q2d(contextIn.time_base); 131 double numberOfInterlacedFramesPerFullFrame = FFMAX(contextIn.ticks_per_frame, 1); 132 133 frameRateOut 134 = possiblyInterlacedFrameRate / numberOfInterlacedFramesPerFullFrame; 135 } 136 137 #endif // UTILITIES_H 138