Disclaimer: This is a bit of a speculation (someone with deeper knowledge, please chime in)
The bottom (obvious) line that you cannot set -pix_fmt
simply because the h264
decoder isn't allowing you to do so.
You can identify which decoder allows modification of the codec parameter via ffmpeg -h decoder=xxx
call. (presumably the same with ffplay
)
First try h264
, which prints:
Decoder h264 [H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10]:
General capabilities: dr1 delay threads
Threading capabilities: frame and slice
Supported hardware devices: dxva2 (null) d3d11va cuda
H264 Decoder AVOptions:
-is_avc <boolean> .D.V..X.... is avc (default false)
-nal_length_size <int> .D.V..X.... nal_length_size (from 0 to 4) (default 0)
-enable_er <boolean> .D.V....... Enable error resilience on damaged frames (unsafe) (default auto)
-x264_build <int> .D.V....... Assume this x264 version if no x264 version found in any SEI (from -1 to INT_MAX) (default -1)
The key line to look for is General capabilities: dr1 delay threads
.
Now, try rawvideo
(which I use extensively and know that you can set pix_fmt
):
Decoder rawvideo [raw video]:
General capabilities: paramchange
Threading capabilities: none
rawdec AVOptions:
-top <boolean> .D.V....... top field first (default auto)
Here General capabilities
lists "paramchange", which wasn't in h264
. This capability appears to be the differentiator.
To investigate further, you find "paramchange"
is displayed by the source code on fftools/opt_common.c#L301:
if (c->capabilities & AV_CODEC_CAP_PARAM_CHANGE)
printf("paramchange ");
and AV_CODEC_CAP_PARAM_CHANGE
is defined on libavcodec/codec.h#L118:
/**
* Codec supports changed parameters at any point.
*/
#define AV_CODEC_CAP_PARAM_CHANGE (1 << 14)
The comment appears to fit our circumstance here (if you interpret it with its opposite condition as "Codec supports changed parameters at no point").