7db15a5685
Cleans up the campaign's exploratory env-gated dumps now that all bugs are fixed: - iter29 LIBVA_HEVC_DUMP_SLICE_TAIL (h265.c) — refuted 40-byte inflation theory - iter30 LIBVA_TS_SCALE (picture.c) — refuted timestamp magnitude theory - iter33 LIBVA_VP8_DUMP_FRAME (vp8.c) — led to α-30 fix - iter35 LIBVA_MPEG2_DUMP_FRAME (mpeg2.c) — confirmed MPEG-2 ctrls correct Total: -131 lines / +7 lines (α-7 comment refresh). Preexisting framework env knobs retained: - LIBVA_V4L2_DUMP_OUTPUT (picture.c α-16) - LIBVA_V4L2_DUMP_CAPTURE (surface.c) - LIBVA_V4L2_ZERO_CAPTURE (picture.c) - LIBVA_V4L2_REQUEST_VIDEO_PATH / MEDIA_PATH / NO_AUTODETECT (request.c) The 3 load-bearing fixes remain unchanged: α-25 (rkvdec image_fmt pre-seed, src/context.c) α-29 (slice_params.short_term_ref_pic_set_size, src/h265.c) α-30 (VP8 OUTPUT header prepend, src/picture.c)
250 lines
9.8 KiB
C
250 lines
9.8 KiB
C
/*
|
|
* Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
|
|
* Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the
|
|
* "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sub license, and/or sell copies of the Software, and to
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
* the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the
|
|
* next paragraph) shall be included in all copies or substantial portions
|
|
* of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
|
* IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
|
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
/*
|
|
* fresnel-fourier iter1 Phase 6 commit B: rewrite against new split
|
|
* V4L2_CID_STATELESS_MPEG2_{SEQUENCE,PICTURE,QUANTISATION} stateless
|
|
* controls (mainline kernel <linux/v4l2-controls.h>:1985-2105).
|
|
*
|
|
* Replaces the staging-era V4L2_CID_MPEG_VIDEO_MPEG2_{SLICE_PARAMS,
|
|
* QUANTIZATION} combined-struct API that the fork previously used
|
|
* via include/mpeg2-ctrls.h (deleted in commit C).
|
|
*
|
|
* Per-frame submission: one batched VIDIOC_S_EXT_CTRLS with three
|
|
* controls (12-byte SEQUENCE + 32-byte PICTURE + 256-byte QUANTISATION),
|
|
* matching FFmpeg libavcodec/v4l2_request_mpeg2.c:130-155 reference
|
|
* implementation. Verified empirically in fresnel-fourier Phase 0
|
|
* cross-validator sweep and Phase 3 Baseline C verbatim payload.
|
|
*
|
|
* Quantisation matrix order: zigzag scanning order per kernel doc
|
|
* v4l2-controls.h:2076. VAAPI VAIQMatrixBufferMPEG2 also stores in
|
|
* zigzag scanning order (per VAAPI spec). Direct memcpy works; no
|
|
* permutation in the libva backend. Kernel hantro_mpeg2.c::
|
|
* hantro_mpeg2_dec_copy_qtable applies the zigzag-to-raster
|
|
* permutation when copying to the hardware quantisation table.
|
|
*
|
|
* Default matrices (when iqmatrix_set==false): MPEG-2 spec defaults
|
|
* per ISO/IEC 13818-2 Table 7-3, transcribed from Phase 3 Baseline C
|
|
* QUANTISATION verbatim payload (256 bytes captured from
|
|
* ffmpeg-v4l2request decode of bbb_720p10s_mpeg2.ts).
|
|
*/
|
|
|
|
#include "mpeg2.h"
|
|
#include "context.h"
|
|
#include "request.h"
|
|
#include "surface.h"
|
|
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
#include <sys/mman.h>
|
|
|
|
#include <linux/videodev2.h>
|
|
#include <linux/v4l2-controls.h>
|
|
|
|
#include "v4l2.h"
|
|
|
|
/*
|
|
* MPEG-2 default intra quantisation matrix in zigzag scanning order
|
|
* (ISO/IEC 13818-2 Table 7-3, verified empirically against
|
|
* fresnel-fourier Phase 3 Baseline C QUANTISATION payload bytes 0..63
|
|
* from a ffmpeg-v4l2request decode of the BBB 720p10s MPEG-2 fixture).
|
|
*/
|
|
static const __u8 mpeg2_default_intra_matrix[64] = {
|
|
8, 16, 16, 19, 16, 19, 22, 22,
|
|
22, 22, 22, 22, 26, 24, 26, 27,
|
|
27, 27, 26, 26, 26, 26, 27, 27,
|
|
27, 29, 29, 29, 34, 34, 34, 29,
|
|
29, 29, 27, 27, 29, 29, 32, 32,
|
|
34, 34, 37, 38, 37, 35, 35, 34,
|
|
35, 38, 38, 40, 40, 40, 48, 48,
|
|
46, 46, 56, 56, 58, 69, 69, 83,
|
|
};
|
|
|
|
/*
|
|
* MPEG-2 default non-intra quantisation matrix is uniformly 16 in spec.
|
|
* Verified against Phase 3 Baseline C QUANTISATION payload bytes
|
|
* 64..127 (all 0x10 = 16). Same applies to chroma_non_intra
|
|
* (bytes 192..255). Filled at runtime via memset rather than a
|
|
* separate const array to keep the binary smaller.
|
|
*/
|
|
|
|
int mpeg2_set_controls(struct request_data *driver_data,
|
|
struct object_context *context_object,
|
|
struct object_surface *surface_object)
|
|
{
|
|
VAPictureParameterBufferMPEG2 *picture =
|
|
&surface_object->params.mpeg2.picture;
|
|
VAIQMatrixBufferMPEG2 *iqmatrix =
|
|
&surface_object->params.mpeg2.iqmatrix;
|
|
bool iqmatrix_set = surface_object->params.mpeg2.iqmatrix_set;
|
|
|
|
/* Clause 2: v4l2_ctrl_mpeg2_sequence (12 bytes) */
|
|
struct v4l2_ctrl_mpeg2_sequence sequence;
|
|
/* Clause 3: v4l2_ctrl_mpeg2_picture (32 bytes; reserved[5] must be zero) */
|
|
struct v4l2_ctrl_mpeg2_picture pic;
|
|
/* Clause 4: v4l2_ctrl_mpeg2_quantisation (256 bytes) */
|
|
struct v4l2_ctrl_mpeg2_quantisation quant;
|
|
|
|
struct object_surface *forward_reference_surface;
|
|
struct object_surface *backward_reference_surface;
|
|
int rc;
|
|
|
|
memset(&sequence, 0, sizeof sequence);
|
|
memset(&pic, 0, sizeof pic); /* zeros pic.reserved[5] per Clause 3 */
|
|
memset(&quant, 0, sizeof quant);
|
|
|
|
/* === Clause 2: SEQUENCE ===
|
|
*
|
|
* VAAPI's VAPictureParameterBufferMPEG2 doesn't expose the
|
|
* sequence-extension's progressive_sequence flag separately;
|
|
* use progressive_frame from the picture-coding extension as a
|
|
* proxy. They're identical for typical streams (BBB is
|
|
* progressive throughout).
|
|
*/
|
|
sequence.horizontal_size = picture->horizontal_size;
|
|
sequence.vertical_size = picture->vertical_size;
|
|
sequence.vbv_buffer_size = surface_object->source_size;
|
|
sequence.profile_and_level_indication = 0; /* not exposed by VAAPI */
|
|
sequence.chroma_format = 1; /* 4:2:0 — campaign codec scope */
|
|
if (picture->picture_coding_extension.bits.progressive_frame)
|
|
sequence.flags |= V4L2_MPEG2_SEQ_FLAG_PROGRESSIVE;
|
|
|
|
/* === Clause 3: PICTURE ===
|
|
*
|
|
* Behavioral correction vs. previous mpeg2.c at this iter1:
|
|
* old code self-referenced surface_object->timestamp when the
|
|
* VAAPI ref picture was VA_INVALID_ID. New code sets ts = 0 for
|
|
* missing refs, matching kernel doc's 0-as-sentinel convention
|
|
* (verified against Phase 3 Baseline C frame 1: I-frame has both
|
|
* forward_ref_ts and backward_ref_ts == 0; FFmpeg
|
|
* libavcodec/v4l2_request_mpeg2.c:98-108 uses same convention).
|
|
*/
|
|
forward_reference_surface =
|
|
SURFACE(driver_data, picture->forward_reference_picture);
|
|
if (forward_reference_surface != NULL)
|
|
pic.forward_ref_ts =
|
|
v4l2_timeval_to_ns(&forward_reference_surface->timestamp);
|
|
|
|
backward_reference_surface =
|
|
SURFACE(driver_data, picture->backward_reference_picture);
|
|
if (backward_reference_surface != NULL)
|
|
pic.backward_ref_ts =
|
|
v4l2_timeval_to_ns(&backward_reference_surface->timestamp);
|
|
|
|
if (picture->picture_coding_extension.bits.top_field_first)
|
|
pic.flags |= V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST;
|
|
if (picture->picture_coding_extension.bits.frame_pred_frame_dct)
|
|
pic.flags |= V4L2_MPEG2_PIC_FLAG_FRAME_PRED_DCT;
|
|
if (picture->picture_coding_extension.bits.concealment_motion_vectors)
|
|
pic.flags |= V4L2_MPEG2_PIC_FLAG_CONCEALMENT_MV;
|
|
if (picture->picture_coding_extension.bits.q_scale_type)
|
|
pic.flags |= V4L2_MPEG2_PIC_FLAG_Q_SCALE_TYPE;
|
|
if (picture->picture_coding_extension.bits.intra_vlc_format)
|
|
pic.flags |= V4L2_MPEG2_PIC_FLAG_INTRA_VLC;
|
|
if (picture->picture_coding_extension.bits.alternate_scan)
|
|
pic.flags |= V4L2_MPEG2_PIC_FLAG_ALT_SCAN;
|
|
if (picture->picture_coding_extension.bits.repeat_first_field)
|
|
pic.flags |= V4L2_MPEG2_PIC_FLAG_REPEAT_FIRST;
|
|
if (picture->picture_coding_extension.bits.progressive_frame)
|
|
pic.flags |= V4L2_MPEG2_PIC_FLAG_PROGRESSIVE;
|
|
|
|
pic.f_code[0][0] = (picture->f_code >> 12) & 0x0f;
|
|
pic.f_code[0][1] = (picture->f_code >> 8) & 0x0f;
|
|
pic.f_code[1][0] = (picture->f_code >> 4) & 0x0f;
|
|
pic.f_code[1][1] = (picture->f_code >> 0) & 0x0f;
|
|
pic.picture_coding_type = picture->picture_coding_type;
|
|
pic.picture_structure =
|
|
picture->picture_coding_extension.bits.picture_structure;
|
|
pic.intra_dc_precision =
|
|
picture->picture_coding_extension.bits.intra_dc_precision;
|
|
/* pic.reserved[5] zeroed by memset above */
|
|
|
|
/* === Clause 4: QUANTISATION ===
|
|
*
|
|
* Kernel always reads all four matrices unconditionally
|
|
* (no load_* flags in the new API; kernel hantro_mpeg2.c
|
|
* doesn't synthesize defaults). When VAAPI's consumer didn't
|
|
* send VAIQMatrixBufferType (iqmatrix_set==false), populate
|
|
* with MPEG-2 spec default matrices.
|
|
*
|
|
* VAAPI VAIQMatrixBufferMPEG2 stores matrices in zigzag scanning
|
|
* order (per VAAPI spec). Kernel expects zigzag scanning order
|
|
* (per v4l2-controls.h:2076). Direct memcpy.
|
|
*/
|
|
if (iqmatrix_set) {
|
|
memcpy(quant.intra_quantiser_matrix,
|
|
iqmatrix->intra_quantiser_matrix, 64);
|
|
memcpy(quant.non_intra_quantiser_matrix,
|
|
iqmatrix->non_intra_quantiser_matrix, 64);
|
|
memcpy(quant.chroma_intra_quantiser_matrix,
|
|
iqmatrix->chroma_intra_quantiser_matrix, 64);
|
|
memcpy(quant.chroma_non_intra_quantiser_matrix,
|
|
iqmatrix->chroma_non_intra_quantiser_matrix, 64);
|
|
} else {
|
|
memcpy(quant.intra_quantiser_matrix,
|
|
mpeg2_default_intra_matrix, 64);
|
|
memset(quant.non_intra_quantiser_matrix, 16, 64);
|
|
memcpy(quant.chroma_intra_quantiser_matrix,
|
|
mpeg2_default_intra_matrix, 64);
|
|
memset(quant.chroma_non_intra_quantiser_matrix, 16, 64);
|
|
}
|
|
|
|
/* === Clause 1+5: batched submission ===
|
|
*
|
|
* One VIDIOC_S_EXT_CTRLS with all three controls. Matches
|
|
* src/h264.c:986 pattern (single v4l2_set_controls call) and
|
|
* FFmpeg ff_v4l2_request_decode_frame contract. Bound to the
|
|
* surface's permanent request_fd (iter6 per-OUTPUT-slot binding;
|
|
* picture.c:284 sets surface_object->request_fd at BeginPicture).
|
|
*/
|
|
struct v4l2_ext_control ctrls[3] = {
|
|
{
|
|
.id = V4L2_CID_STATELESS_MPEG2_SEQUENCE,
|
|
.ptr = &sequence,
|
|
.size = sizeof sequence,
|
|
},
|
|
{
|
|
.id = V4L2_CID_STATELESS_MPEG2_PICTURE,
|
|
.ptr = &pic,
|
|
.size = sizeof pic,
|
|
},
|
|
{
|
|
.id = V4L2_CID_STATELESS_MPEG2_QUANTISATION,
|
|
.ptr = &quant,
|
|
.size = sizeof quant,
|
|
},
|
|
};
|
|
|
|
rc = v4l2_set_controls(driver_data->video_fd,
|
|
surface_object->request_fd,
|
|
ctrls, 3);
|
|
if (rc < 0)
|
|
return VA_STATUS_ERROR_OPERATION_FAILED;
|
|
|
|
return 0;
|
|
}
|