I'm trying to follow the "learn ffmpeg the hard way" guide on github (https://github.com/leandromoreira/ffmpeg-libav-tutorial#chapter-2---remuxing) and when I try to run the remuxing code for myself using a C++ compiler I always get the error
invalid conversion from ‘int’ to ‘AVRounding’[-fpermissive]
The only real difference between my code and the github original is that I take the input filename and output filename as parameters instead. Doing some resarch I have found that AVRounding is a enum? I think? Thus I need to explicitly cast somehow. However I'm failing to understand how explicit casting works and how I would use it to solve my issue. Where would I cast it? Here's the line that causes the issue:
packet.pts = av_rescale_q_rnd(packet.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
packet.dts = av_rescale_q_rnd(packet.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
Could anyone explain how to solve the issue? Sorry if it's a beginners mistake. Thanks in advance for any help.
AVRounding
is indeed an enum (to be exact, an unscoped enum without a fixed underlying type):
/**
* Rounding methods.
*/
enum AVRounding {
AV_ROUND_ZERO = 0, ///< Round toward zero.
AV_ROUND_INF = 1, ///< Round away from zero.
AV_ROUND_DOWN = 2, ///< Round toward -infinity.
AV_ROUND_UP = 3, ///< Round toward +infinity.
AV_ROUND_NEAR_INF = 5, ///< Round to nearest and halfway cases away from zero.
/**
* Flag telling rescaling functions to pass `INT64_MIN`/`MAX` through
* unchanged, avoiding special cases for #AV_NOPTS_VALUE.
*
* Unlike other values of the enumeration AVRounding, this value is a
* bitmask that must be used in conjunction with another value of the
* enumeration through a bitwise OR, in order to set behavior for normal
* cases.
*
* @code{.c}
* av_rescale_rnd(3, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX);
* // Rescaling 3:
* // Calculating 3 * 1 / 2
* // 3 / 2 is rounded up to 2
* // => 2
*
* av_rescale_rnd(AV_NOPTS_VALUE, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX);
* // Rescaling AV_NOPTS_VALUE:
* // AV_NOPTS_VALUE == INT64_MIN
* // AV_NOPTS_VALUE is passed through
* // => AV_NOPTS_VALUE
* @endcode
*/
AV_ROUND_PASS_MINMAX = 8192,
};
The values you are trying to pass to av_rescale_q_rnd()
are not themselves int
s, but they are implicitly convertible to int
. However, C++ does not allow an int
to be implicitly converted to a enum
, and FFmpeg does not define an operator|
for AVRounding
in C++, so the result of OR'ing the values of AV_ROUND_NEAR_INF
and AV_ROUND_PASS_MINMAX
together actually does produce an int
, hence the need for a type-cast to go back to an AVRounding
, eg:
packet.pts = av_rescale_q_rnd(..., static_cast<AVRounding>(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
packet.dts = av_rescale_q_rnd(..., static_cast<AVRounding>(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
You can manually define an operator|
to avoid that type-casting at the call site, if you wish, eg:
inline AVRounding operator|(AVRounding a, AVRounding b)
{
return static_cast<AVRounding>(static_cast<int>(a) | static_cast<int>(b));
}
...
packet.pts = av_rescale_q_rnd(..., AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
packet.dts = av_rescale_q_rnd(..., AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);