I am trying to write a decoder using ffmpeg and I want to display some information about the video stream. I can detect if a frame is progressive or interlaced (tff, bff) only after decoding the frame. i.e,
avcodec_decode_video2(pCodecCtx, pFrame, &gotFrame, &packet);
.....(assume we have a frame)
.....
// print information
printf("prog=%d inter=%d", !pFrame->interlaced_frame, pFrame->interlaced_frame);
This works well.
But I want to know if there is a way of detecting this from the AVFormatContext, AVCodecCtx or AVCodec structs or some other functions. This would be very useful, if for example I want to abort decoding if the file is interlaced. I don't want to decode a frame to get this piece of information.
I am trying to support MPEG2, H.264/AVC and HEVC codecs (either elementary streams or in MP4 container).
Sorry if this is a trivial question! Thank you very much!
ffmpeg can run in "idet" (interlace detection) mode and gives a summary of frame types it finds in the file. I use:
$ ffmpeg -filter:v idet -frames:v 360 -an -f rawvideo -y /dev/null -i HitchhikersGuide.mp4
(ffmpeg with the idet filter, sample 360 frames, blocking audio, using rawvideo format, send output to /dev/null, with input file HitchhikersGuide.mp4)
which produces a report that contains (in part):
[Parsed_idet_0 @ 0x7fd5f3c121c0] Repeated Fields: Neither: 360 Top: 0 Bottom: 0
[Parsed_idet_0 @ 0x7fd5f3c121c0] Single frame detection: TFF: 30 BFF: 0 Progressive: 330 Undetermined: 0
[Parsed_idet_0 @ 0x7fd5f3c121c0] Multi frame detection: TFF: 22 BFF: 0 Progressive: 338 Undetermined: 0
In this case, 92% of the sampled frames are progressive, and 8% are interlaced, so most services would call this an interlaced video. TFF and BFF are Top-Field-First and Bottom-Field-First, respectively, and both indicate an interlaced frame.
Note that it is possible to encode interlaced video as progressive and progressive video as interlaced, and this method will report on the encoding only. If you want to know if the video was originally interlaced or progressive, then you will need to visually inspect it and look for a "combing" effect where alternate lines don't quite line up with each other (especially when the camera is moving fast), and if you see combing, then the original video is interlaced.
You could use ffprobe, which comes with ffmpeg. I don't know how you would use that from a library, but the command-line version can show the field_order
.
Example command, with a few additional fields:
ffprobe -v quiet -select_streams v stream=codec_name,height,width,pix_fmt,field_order -of csv=p=0 "$Your_File"
Example output with different files:
prores,1920,1080,yuva444p12le,progressive
h264,1920,1080,yuv420p,unknown # some progressive files show unknown
prores,720,576,yuv422p10le,tb # tb = interlaced TFF interleaved
mpeg2video,1920,1080,yuv422p,tt # tt = interlaced TFF
dvvideo,720,576,yuv420p,bt # bt = interlaced BFF interleaved
An alternative would be Mediainfo :
mediainfo --Inform='Video;%ScanType%,%ScanOrder%,%ScanType_StoreMethod%' "$Your_File"
Example output with different files:
Progressive,,
Interlaced,TFF,
Interlaced,TFF,InterleavedFields
Interlaced,BFF,InterleavedFields
Mediainfo's source is available here, and on Github.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With