Opened 16 months ago

#11565 new enhancement

dshow wrapper packet AV_PKT_FLAG_KEY flagging

Reported by: Matt Carpenter Owned by:
Priority: normal Component: avformat
Version: 6.1.1 Keywords: dshow
Cc: Matt Carpenter Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

Summary of the enhancement:
Explanation:

% ffprobe -f dshow -video_pin_name 1 -i video="H264 USB Camera" -show_entries frame=key_frame

ffmpeg version
libavutil      56. 63.100 / 56. 63.100
libavcodec     58.115.102 / 58.115.102
libavformat    58. 65.101 / 58. 65.101
libavdevice    58. 11.103 / 58. 11.103
libavfilter     7. 95.100 /  7. 95.100
libswscale      5.  8.100 /  5.  8.100
libswresample   3.  8.100 /  3.  8.100
libpostproc    55.  8.100 / 55.  8.100

The above command displays key_frames coming from my USB camera once-per-second. Camera is ELP-USBFHD06H-BL170 with the h264 stream on video pin 1. Inside my recorder program the following code is used to try and detect key_frames on the same camera.

input->input_ctx = avformat_alloc_context();
input->input_ctx->video_codec_id = AV_CODEC_ID_H264;
...
av_read_frame(input->input_ctx, in_packet);
in_packet->flags & AV_PKT_FLAG_KEY) == AV_PKT_FLAG_KEY

The code above does not detect any packets having the key_frame flag set.
Original question asked and answered: https://superuser.com/questions/1888999/trying-to-understand-how-key-frames-work-when-using-ffmpeg-on-windows-with-a-usb

A workaround for my program was the following code to search for any IDR NAL units inside the packet, and consider any packets containing IDR NAL units as keyfames.

/*
* Look inside the packet's frame buffer for NAL units of type IDR frame
* @returns 0 if not 1 if found 
*/
int is_idr_frame(AVPacket *pkt) {
    if (pkt->size < 6) return 0;  // Ensure packet is large enough for parsing
    const uint8_t *data = pkt->data;

    // Look for NAL unit start codes (00 00 00 01 or 00 00 01)
    for (int i = 0; i < pkt->size - 4; i++) {
        if (data[i] == 0x00 && data[i + 1] == 0x00 &&
            ((data[i + 2] == 0x01) || (data[i + 2] == 0x00 && data[i + 3] == 0x01))) {
            uint8_t nal_type = data[i + 2] == 0x01 ? (data[i + 3] & 0x1F) : (data[i + 4] & 0x1F);
            if (nal_type == 5)  // NAL type 5 = IDR frame
                return 1;
        }
    }
    return 0;
}

Suggested enhancement for dshow wrapper - set the AV_PKT_FLAG_KEY on AVPacket.

Change History (0)

Note: See TracTickets for help on using tickets.