Showing the changes to libavcodec/vaapi_encode_mpeg2.c (1 of 2 files). Show all
Unified · Split
| @@ -20,15 +20,11 @@ · 19 unmodified lines | |||
| 20 | #include <va/va_enc_mpeg2.h> | 20 | #include <va/va_enc_mpeg2.h> |
| 21 | 21 | ||
| 22 | #include "libavutil/avassert.h" | 22 | #include "libavutil/avassert.h" |
| 23 | #include "libavutil/common.h" | ||
| 24 | #include "libavutil/internal.h" | ||
| 25 | #include "libavutil/opt.h" | ||
| 26 | #include "libavutil/pixfmt.h" | ||
| 27 | 23 | ||
| 28 | #include "avcodec.h" | 24 | #include "avcodec.h" |
| 29 | #include "internal.h" | 25 | #include "cbs.h" |
| 30 | #include "mpegvideo.h" | 26 | #include "cbs_mpeg2.h" |
| 31 | #include "put_bits.h" | 27 | #include "mpeg12.h" |
| 32 | #include "vaapi_encode.h" | 28 | #include "vaapi_encode.h" |
| 33 | 29 | ||
| 34 | typedef struct VAAPIEncodeMPEG2Context { | 30 | typedef struct VAAPIEncodeMPEG2Context { |
| @@ -39,79 +35,104 @@ typedef struct VAAPIEncodeMPEG2Context { · 4 unmodified lines | |||
| 39 | int quant_p; | 35 | int quant_p; |
| 40 | int quant_b; | 36 | int quant_b; |
| 41 | 37 | ||
| 38 | MPEG2RawSequenceHeader sequence_header; | ||
| 39 | MPEG2RawExtensionData sequence_extension; | ||
| 40 | MPEG2RawExtensionData sequence_display_extension; | ||
| 41 | MPEG2RawGroupOfPicturesHeader gop_header; | ||
| 42 | MPEG2RawPictureHeader picture_header; | ||
| 43 | MPEG2RawExtensionData picture_coding_extension; | ||
| 44 | |||
| 42 | int64_t last_i_frame; | 45 | int64_t last_i_frame; |
| 43 | 46 | ||
| 44 | unsigned int bit_rate; | 47 | unsigned int bit_rate; |
| 45 | unsigned int vbv_buffer_size; | 48 | unsigned int vbv_buffer_size; |
| 49 | |||
| 50 | AVRational frame_rate; | ||
| 51 | |||
| 52 | unsigned int f_code_horizontal; | ||
| 53 | unsigned int f_code_vertical; | ||
| 54 | |||
| 55 | CodedBitstreamContext cbc; | ||
| 56 | CodedBitstreamFragment current_fragment; | ||
| 46 | } VAAPIEncodeMPEG2Context; | 57 | } VAAPIEncodeMPEG2Context; |
| 47 | 58 | ||
| 48 | 59 | ||
| 49 | #define vseq_var(name) vseq->name, name | 60 | static int vaapi_encode_mpeg2_write_fragment(AVCodecContext *avctx, |
| 50 | #define vseqext_field(name) vseq->sequence_extension.bits.name, name | 61 | char *data, size_t *data_len, |
| 51 | #define vgop_field(name) vseq->gop_header.bits.name, name | 62 | CodedBitstreamFragment *frag) |
| 52 | #define vpic_var(name) vpic->name, name | 63 | { |
| 53 | #define vpcext_field(name) vpic->picture_coding_extension.bits.name, name | 64 | VAAPIEncodeContext *ctx = avctx->priv_data; |
| 54 | #define vcomp_field(name) vpic->composite_display.bits.name, name | 65 | VAAPIEncodeMPEG2Context *priv = ctx->priv_data; |
| 66 | int err; | ||
| 67 | |||
| 68 | err = ff_cbs_write_fragment_data(&priv->cbc, frag); | ||
| 69 | if (err < 0) { | ||
| 70 | av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); | ||
| 71 | return err; | ||
| 72 | } | ||
| 73 | |||
| 74 | if (*data_len < 8 * frag->data_size - frag->data_bit_padding) { | ||
| 75 | av_log(avctx, AV_LOG_ERROR, "Access unit too large: " | ||
| 76 | "%zu < %zu.\n", *data_len, | ||
| 77 | 8 * frag->data_size - frag->data_bit_padding); | ||
| 78 | return AVERROR(ENOSPC); | ||
| 79 | } | ||
| 80 | |||
| 81 | memcpy(data, frag->data, frag->data_size); | ||
| 82 | *data_len = 8 * frag->data_size - frag->data_bit_padding; | ||
| 83 | |||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | static int vaapi_encode_mpeg2_add_header(AVCodecContext *avctx, | ||
| 88 | CodedBitstreamFragment *frag, | ||
| 89 | int type, void *header) | ||
| 90 | { | ||
| 91 | VAAPIEncodeContext *ctx = avctx->priv_data; | ||
| 92 | VAAPIEncodeMPEG2Context *priv = ctx->priv_data; | ||
| 93 | int err; | ||
| 94 | |||
| 95 | err = ff_cbs_insert_unit_content(&priv->cbc, frag, -1, type, header); | ||
| 96 | if (err < 0) { | ||
| 97 | av_log(avctx, AV_LOG_ERROR, "Failed to add header: " | ||
| 98 | "type = %d.\n", type); | ||
| 99 | return err; | ||
| 100 | } | ||
| 55 | 101 | ||
| 56 | #define u2(width, value, name) put_bits(&pbc, width, value) | 102 | return 0; |
| 57 | #define u(width, ...) u2(width, __VA_ARGS__) | 103 | } |
| 58 | 104 | ||
| 59 | static int vaapi_encode_mpeg2_write_sequence_header(AVCodecContext *avctx, | 105 | static int vaapi_encode_mpeg2_write_sequence_header(AVCodecContext *avctx, |
| 60 | char *data, size_t *data_len) | 106 | char *data, size_t *data_len) |
| 61 | { | 107 | { |
| 62 | VAAPIEncodeContext *ctx = avctx->priv_data; | 108 | VAAPIEncodeContext *ctx = avctx->priv_data; |
| 63 | VAEncSequenceParameterBufferMPEG2 *vseq = ctx->codec_sequence_params; | 109 | VAAPIEncodeMPEG2Context *priv = ctx->priv_data; |
| 64 | VAAPIEncodeMPEG2Context *priv = ctx->priv_data; | 110 | CodedBitstreamFragment *frag = &priv->current_fragment; |
| 65 | PutBitContext pbc; | 111 | int err; |
| 66 | 112 | ||
| 67 | init_put_bits(&pbc, data, 8 * *data_len); | 113 | err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_SEQUENCE_HEADER, |
| 68 | 114 | &priv->sequence_header); | |
| 69 | u(32, SEQ_START_CODE, sequence_header_code); | 115 | if (err < 0) |
| 70 | 116 | goto fail; | |
| 71 | u(12, vseq->picture_width, horizontal_size_value); | 117 | |
| 72 | u(12, vseq->picture_height, vertical_size_value); | 118 | err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_EXTENSION, |
| 73 | u(4, vseq_var(aspect_ratio_information)); | 119 | &priv->sequence_extension); |
| 74 | u(4, 8, frame_rate_code); | 120 | if (err < 0) |
| 75 | u(18, priv->bit_rate & 0x3fff, bit_rate_value); | 121 | goto fail; |
| 76 | u(1, 1, marker_bit); | 122 | |
| 77 | u(10, priv->vbv_buffer_size & 0x3ff, vbv_buffer_size_value); | 123 | err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_EXTENSION, |
| 78 | u(1, 0, constrained_parameters_flag); | 124 | &priv->sequence_display_extension); |
| 79 | u(1, 0, load_intra_quantiser_matrix); | 125 | if (err < 0) |
| 80 | // intra_quantiser_matrix[64] | 126 | goto fail; |
| 81 | u(1, 0, load_non_intra_quantiser_matrix); | 127 | |
| 82 | // non_intra_quantiser_matrix[64] | 128 | err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_GROUP, |
| 83 | 129 | &priv->gop_header); | |
| 84 | while (put_bits_count(&pbc) % 8) | 130 | if (err < 0) |
| 85 | u(1, 0, zero_bit); | 131 | goto fail; |
| 86 | 132 | ||
| 87 | u(32, EXT_START_CODE, extension_start_code); | 133 | err = vaapi_encode_mpeg2_write_fragment(avctx, data, data_len, frag); |
| 88 | u(4, 1, extension_start_code_identifier); | 134 | fail: |
| 89 | u(8, vseqext_field(profile_and_level_indication)); | 135 | ff_cbs_fragment_uninit(&priv->cbc, frag); |
| 90 | u(1, vseqext_field(progressive_sequence)); | ||
| 91 | u(2, vseqext_field(chroma_format)); | ||
| 92 | u(2, 0, horizontal_size_extension); | ||
| 93 | u(2, 0, vertical_size_extension); | ||
| 94 | u(12, priv->bit_rate >> 18, bit_rate_extension); | ||
| 95 | u(1, 1, marker_bit); | ||
| 96 | u(8, priv->vbv_buffer_size >> 10, vbv_buffer_size_extension); | ||
| 97 | u(1, vseqext_field(low_delay)); | ||
| 98 | u(2, vseqext_field(frame_rate_extension_n)); | ||
| 99 | u(2, vseqext_field(frame_rate_extension_d)); | ||
| 100 | |||
| 101 | while (put_bits_count(&pbc) % 8) | ||
| 102 | u(1, 0, zero_bit); | ||
| 103 | |||
| 104 | u(32, GOP_START_CODE, group_start_code); | ||
| 105 | u(25, vgop_field(time_code)); | ||
| 106 | u(1, vgop_field(closed_gop)); | ||
| 107 | u(1, vgop_field(broken_link)); | ||
| 108 | |||
| 109 | while (put_bits_count(&pbc) % 8) | ||
| 110 | u(1, 0, zero_bit); | ||
| 111 | |||
| 112 | *data_len = put_bits_count(&pbc); | ||
| 113 | flush_put_bits(&pbc); | ||
| 114 | |||
| 115 | return 0; | 136 | return 0; |
| 116 | } | 137 | } |
| 117 | 138 | ||
| @@ -119,139 +140,275 @@ static int vaapi_encode_mpeg2_write_picture_header(AVCodecContext *avctx, · 1 unmodified line | |||
| 119 | VAAPIEncodePicture *pic, | 140 | VAAPIEncodePicture *pic, |
| 120 | char *data, size_t *data_len) | 141 | char *data, size_t *data_len) |
| 121 | { | 142 | { |
| 122 | VAEncPictureParameterBufferMPEG2 *vpic = pic->codec_picture_params; | 143 | VAAPIEncodeContext *ctx = avctx->priv_data; |
| 123 | int picture_coding_type; | 144 | VAAPIEncodeMPEG2Context *priv = ctx->priv_data; |
| 124 | PutBitContext pbc; | 145 | CodedBitstreamFragment *frag = &priv->current_fragment; |
| 146 | int err; | ||
| 147 | |||
| 148 | err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_PICTURE, | ||
| 149 | &priv->picture_header); | ||
| 150 | if (err < 0) | ||
| 151 | goto fail; | ||
| 152 | |||
| 153 | err = vaapi_encode_mpeg2_add_header(avctx, frag, MPEG2_START_EXTENSION, | ||
| 154 | &priv->picture_coding_extension); | ||
| 155 | if (err < 0) | ||
| 156 | goto fail; | ||
| 157 | |||
| 158 | err = vaapi_encode_mpeg2_write_fragment(avctx, data, data_len, frag); | ||
| 159 | fail: | ||
| 160 | ff_cbs_fragment_uninit(&priv->cbc, frag); | ||
| 161 | return 0; | ||
| 162 | } | ||
| 125 | 163 | ||
| 126 | init_put_bits(&pbc, data, 8 * *data_len); | 164 | static int vaapi_encode_mpeg2_init_sequence_params(AVCodecContext *avctx) |
| 165 | { | ||
| 166 | VAAPIEncodeContext *ctx = avctx->priv_data; | ||
| 167 | VAAPIEncodeMPEG2Context *priv = ctx->priv_data; | ||
| 168 | MPEG2RawSequenceHeader *sh = &priv->sequence_header; | ||
| 169 | MPEG2RawSequenceExtension *se = &priv->sequence_extension.data.sequence; | ||
| 170 | MPEG2RawSequenceDisplayExtension *sde = &priv->sequence_display_extension.data.sequence_display; | ||
| 171 | MPEG2RawGroupOfPicturesHeader *goph = &priv->gop_header; | ||
| 172 | MPEG2RawPictureHeader *ph = &priv->picture_header; | ||
| 173 | MPEG2RawPictureCodingExtension *pce = &priv->picture_coding_extension.data.picture_coding; | ||
| 174 | VAEncSequenceParameterBufferMPEG2 *vseq = ctx->codec_sequence_params; | ||
| 175 | VAEncPictureParameterBufferMPEG2 *vpic = ctx->codec_picture_params; | ||
| 176 | int code, ext_n, ext_d; | ||
| 127 | 177 | ||
| 128 | u(32, PICTURE_START_CODE, picture_start_code); | 178 | memset(sh, 0, sizeof(*sh)); |
| 129 | u(10, vpic_var(temporal_reference)); | 179 | memset(se, 0, sizeof(*se)); |
| 180 | memset(sde, 0, sizeof(*sde)); | ||
| 181 | memset(goph, 0, sizeof(*goph)); | ||
| 182 | memset(ph, 0, sizeof(*ph)); | ||
| 183 | memset(pce, 0, sizeof(*pce)); | ||
| 130 | 184 | ||
| 131 | switch (vpic->picture_type) { | 185 | |
| 132 | case VAEncPictureTypeIntra: | 186 | if (avctx->bit_rate > 0) { |
| 133 | picture_coding_type = AV_PICTURE_TYPE_I; | 187 | priv->bit_rate = (avctx->bit_rate + 399) / 400; |
| 134 | break; | 188 | } else { |
| 135 | case VAEncPictureTypePredictive: | 189 | // Unknown (not a bitrate-targetting mode), so just use the |
| 136 | picture_coding_type = AV_PICTURE_TYPE_P; | 190 | // highest value. |
| 191 | priv->bit_rate = 0x3fffffff; | ||
| 192 | } | ||
| 193 | if (avctx->rc_buffer_size > 0) { | ||
| 194 | priv->vbv_buffer_size = (avctx->rc_buffer_size + (1 << 14) - 1) >> 14; | ||
| 195 | } else { | ||
| 196 | // Unknown, so guess a value from the bitrate. | ||
| 197 | priv->vbv_buffer_size = priv->bit_rate >> 14; | ||
| 198 | } | ||
| 199 | |||
| 200 | switch (avctx->level) { | ||
| 201 | case 4: // High. | ||
| 202 | case 6: // High 1440. | ||
| 203 | priv->f_code_horizontal = 9; | ||
| 204 | priv->f_code_vertical = 5; | ||
| 137 | break; | 205 | break; |
| 138 | case VAEncPictureTypeBidirectional: | 206 | case 8: // Main. |
| 139 | picture_coding_type = AV_PICTURE_TYPE_B; | 207 | priv->f_code_horizontal = 8; |
| 208 | priv->f_code_vertical = 5; | ||
| 140 | break; | 209 | break; |
| 210 | case 10: // Low. | ||
| 141 | default: | 211 | default: |
| 142 | av_assert0(0 && "invalid picture_coding_type"); | 212 | priv->f_code_horizontal = 7; |
| 143 | } | 213 | priv->f_code_vertical = 4; |
| 144 | u(3, picture_coding_type, picture_coding_type); | 214 | break; |
| 145 | u(16, 0xffff, vbv_delay); | ||
| 146 | if (picture_coding_type == 2 || picture_coding_type == 3) { | ||
| 147 | u(1, 0, full_pel_forward_vector); | ||
| 148 | u(3, 7, forward_f_code); | ||
| 149 | } | ||
| 150 | if (picture_coding_type == 3) { | ||
| 151 | u(1, 0, full_pel_backward_vector); | ||
| 152 | u(3, 7, backward_f_code); | ||
| 153 | } | 215 | } |
| 154 | u(1, 0, extra_bit_picture); | 216 | |
| 155 | 217 | ||
| 156 | while (put_bits_count(&pbc) % 8) | 218 | // Sequence header |
| 157 | u(1, 0, zero_bit); | 219 | |
| 158 | 220 | sh->sequence_header_code = MPEG2_START_SEQUENCE_HEADER; | |
| 159 | u(32, EXT_START_CODE, extension_start_code); | 221 | |
| 160 | u(4, 8, extension_start_code_identifier); | 222 | sh->horizontal_size_value = avctx->width & 0xfff; |
| 161 | u(4, vpic_var(f_code[0][0])); | 223 | sh->vertical_size_value = avctx->height & 0xfff; |
| 162 | u(4, vpic_var(f_code[0][1])); | 224 | |
| 163 | u(4, vpic_var(f_code[1][0])); | 225 | if (avctx->sample_aspect_ratio.num != 0 && |
| 164 | u(4, vpic_var(f_code[1][1])); | 226 | avctx->sample_aspect_ratio.den != 0) { |
| 165 | u(2, vpcext_field(intra_dc_precision)); | 227 | AVRational dar = av_div_q(avctx->sample_aspect_ratio, |
| 166 | u(2, vpcext_field(picture_structure)); | 228 | (AVRational) { avctx->width, avctx->height }); |
| 167 | u(1, vpcext_field(top_field_first)); | 229 | |
| 168 | u(1, vpcext_field(frame_pred_frame_dct)); | 230 | if (av_cmp_q(avctx->sample_aspect_ratio, (AVRational) { 1, 1 }) == 0) { |
| 169 | u(1, vpcext_field(concealment_motion_vectors)); | 231 | sh->aspect_ratio_information = 1; |
| 170 | u(1, vpcext_field(q_scale_type)); | 232 | } else if (av_cmp_q(dar, (AVRational) { 3, 4 }) == 0) { |
| 171 | u(1, vpcext_field(intra_vlc_format)); | 233 | sh->aspect_ratio_information = 2; |
| 172 | u(1, vpcext_field(alternate_scan)); | 234 | } else if (av_cmp_q(dar, (AVRational) { 9, 16 }) == 0) { |
| 173 | u(1, vpcext_field(repeat_first_field)); | 235 | sh->aspect_ratio_information = 3; |
| 174 | u(1, 1, chroma_420_type); | 236 | } else if (av_cmp_q(dar, (AVRational) { 100, 221 }) == 0) { |
| 175 | u(1, vpcext_field(progressive_frame)); | 237 | sh->aspect_ratio_information = 4; |
| 176 | u(1, vpcext_field(composite_display_flag)); | 238 | } else { |
| 177 | if (vpic->picture_coding_extension.bits.composite_display_flag) { | 239 | av_log(avctx, AV_LOG_WARNING, "Sample aspect ratio %d:%d is not " |
| 178 | u(1, vcomp_field(v_axis)); | 240 | "representable, signalling square pixels instead.\n", |
| 179 | u(3, vcomp_field(field_sequence)); | 241 | avctx->sample_aspect_ratio.num, |
| 180 | u(1, vcomp_field(sub_carrier)); | 242 | avctx->sample_aspect_ratio.den); |
| 181 | u(7, vcomp_field(burst_amplitude)); | 243 | sh->aspect_ratio_information = 1; |
| 182 | u(8, vcomp_field(sub_carrier_phase)); | 244 | } |
| 245 | } else { | ||
| 246 | // Unknown - assume square pixels. | ||
| 247 | sh->aspect_ratio_information = 1; | ||
| 183 | } | 248 | } |
| 184 | 249 | ||
| 185 | while (put_bits_count(&pbc) % 8) | 250 | if (avctx->framerate.num > 0 && avctx->framerate.den > 0) |
| 186 | u(1, 0, zero_bit); | 251 | priv->frame_rate = avctx->framerate; |
| 252 | else | ||
| 253 | priv->frame_rate = av_inv_q(avctx->time_base); | ||
| 254 | ff_mpeg12_find_best_frame_rate(priv->frame_rate, | ||
| 255 | &code, &ext_n, &ext_d, 0); | ||
| 256 | sh->frame_rate_code = code; | ||
| 187 | 257 | ||
| 188 | *data_len = put_bits_count(&pbc); | 258 | sh->bit_rate_value = priv->bit_rate & 0x3ffff; |
| 189 | flush_put_bits(&pbc); | 259 | sh->vbv_buffer_size_value = priv->vbv_buffer_size & 0x3ff; |
| 190 | 260 | ||
| 191 | return 0; | 261 | sh->constrained_parameters_flag = 0; |
| 192 | } | 262 | sh->load_intra_quantiser_matrix = 0; |
| 263 | sh->load_non_intra_quantiser_matrix = 0; | ||
| 193 | 264 | ||
| 194 | static int vaapi_encode_mpeg2_init_sequence_params(AVCodecContext *avctx) | ||
| 195 | { | ||
| 196 | VAAPIEncodeContext *ctx = avctx->priv_data; | ||
| 197 | VAEncSequenceParameterBufferMPEG2 *vseq = ctx->codec_sequence_params; | ||
| 198 | VAEncPictureParameterBufferMPEG2 *vpic = ctx->codec_picture_params; | ||
| 199 | VAAPIEncodeMPEG2Context *priv = ctx->priv_data; | ||
| 200 | 265 | ||
| 201 | vseq->intra_period = avctx->gop_size; | 266 | // Sequence extension |
| 202 | vseq->ip_period = ctx->b_per_p + 1; | ||
| 203 | 267 | ||
| 204 | vseq->picture_width = avctx->width; | 268 | priv->sequence_extension.extension_start_code = MPEG2_START_EXTENSION; |
| 205 | vseq->picture_height = avctx->height; | 269 | priv->sequence_extension.extension_start_code_identifier = |
| 270 | MPEG2_EXTENSION_SEQUENCE; | ||
| 206 | 271 | ||
| 207 | vseq->bits_per_second = avctx->bit_rate; | 272 | se->profile_and_level_indication = avctx->profile << 4 | avctx->level; |
| 208 | if (avctx->framerate.num > 0 && avctx->framerate.den > 0) | 273 | se->progressive_sequence = 1; |
| 209 | vseq->frame_rate = (float)avctx->framerate.num / avctx->framerate.den; | 274 | se->chroma_format = 1; |
| 210 | else | 275 | |
| 211 | vseq->frame_rate = (float)avctx->time_base.num / avctx->time_base.den; | 276 | se->horizontal_size_extension = avctx->width >> 12; |
| 212 | 277 | se->vertical_size_extension = avctx->height >> 12; | |
| 213 | vseq->aspect_ratio_information = 1; | 278 | |
| 214 | vseq->vbv_buffer_size = avctx->rc_buffer_size / (16 * 1024); | 279 | se->bit_rate_extension = priv->bit_rate >> 18; |
| 215 | 280 | se->vbv_buffer_size_extension = priv->vbv_buffer_size >> 10; | |
| 216 | vseq->sequence_extension.bits.profile_and_level_indication = | 281 | se->low_delay = ctx->b_per_p == 0; |
| 217 | avctx->profile << 4 | avctx->level; | 282 | |
| 218 | vseq->sequence_extension.bits.progressive_sequence = 1; | 283 | se->frame_rate_extension_n = ext_n; |
| 219 | vseq->sequence_extension.bits.chroma_format = 1; | 284 | se->frame_rate_extension_d = ext_d; |
| 220 | vseq->sequence_extension.bits.low_delay = 0; | 285 | |
| 221 | vseq->sequence_extension.bits.frame_rate_extension_n = 0; | 286 | |
| 222 | vseq->sequence_extension.bits.frame_rate_extension_d = 0; | 287 | // Sequence display extension |
| 223 | 288 | ||
| 224 | vseq->new_gop_header = 0; | 289 | priv->sequence_display_extension.extension_start_code = |
| 225 | vseq->gop_header.bits.time_code = 0; | 290 | MPEG2_START_EXTENSION; |
| 226 | vseq->gop_header.bits.closed_gop = 1; | 291 | priv->sequence_display_extension.extension_start_code_identifier = |
| 227 | vseq->gop_header.bits.broken_link = 0; | 292 | MPEG2_EXTENSION_SEQUENCE_DISPLAY; |
| 228 | 293 | ||
| 229 | vpic->forward_reference_picture = VA_INVALID_ID; | 294 | sde->video_format = 5; |
| 230 | vpic->backward_reference_picture = VA_INVALID_ID; | 295 | if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || |
| 231 | vpic->reconstructed_picture = VA_INVALID_ID; | 296 | avctx->color_trc != AVCOL_TRC_UNSPECIFIED || |
| 232 | 297 | avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { | |
| 233 | vpic->coded_buf = VA_INVALID_ID; | 298 | sde->colour_description = 1; |
| 234 | 299 | sde->colour_primaries = avctx->color_primaries; | |
| 235 | vpic->temporal_reference = 0; | 300 | sde->transfer_characteristics = avctx->color_trc; |
| 236 | vpic->f_code[0][0] = 15; | 301 | sde->matrix_coefficients = avctx->colorspace; |
| 237 | vpic->f_code[0][1] = 15; | 302 | } else { |
| 238 | vpic->f_code[1][0] = 15; | 303 | sde->colour_description = 0; |
| 239 | vpic->f_code[1][1] = 15; | 304 | } |
| 240 | 305 | ||
| 241 | vpic->picture_coding_extension.bits.intra_dc_precision = 0; | 306 | sde->display_horizontal_size = avctx->width; |
| 242 | vpic->picture_coding_extension.bits.picture_structure = 3; | 307 | sde->display_vertical_size = avctx->height; |
| 243 | vpic->picture_coding_extension.bits.top_field_first = 0; | 308 | |
| 244 | vpic->picture_coding_extension.bits.frame_pred_frame_dct = 1; | 309 | |
| 245 | vpic->picture_coding_extension.bits.concealment_motion_vectors = 0; | 310 | // GOP header |
| 246 | vpic->picture_coding_extension.bits.q_scale_type = 0; | 311 | |
| 247 | vpic->picture_coding_extension.bits.intra_vlc_format = 0; | 312 | goph->group_start_code = MPEG2_START_GROUP; |
| 248 | vpic->picture_coding_extension.bits.alternate_scan = 0; | 313 | |
| 249 | vpic->picture_coding_extension.bits.repeat_first_field = 0; | 314 | goph->time_code = 0; |
| 250 | vpic->picture_coding_extension.bits.progressive_frame = 1; | 315 | goph->closed_gop = 1; |
| 251 | vpic->picture_coding_extension.bits.composite_display_flag = 0; | 316 | goph->broken_link = 0; |
| 252 | 317 | ||
| 253 | priv->bit_rate = (avctx->bit_rate + 399) / 400; | 318 | |
| 254 | priv->vbv_buffer_size = avctx->rc_buffer_size / (16 * 1024); | 319 | // Defaults for picture header |
| 320 | |||
| 321 | ph->picture_start_code = MPEG2_START_PICTURE; | ||
| 322 | |||
| 323 | ph->vbv_delay = 0xffff; // Not currently calculated. | ||
| 324 | |||
| 325 | ph->full_pel_forward_vector = 0; | ||
| 326 | ph->forward_f_code = 7; | ||
| 327 | ph->full_pel_backward_vector = 0; | ||
| 328 | ph->forward_f_code = 7; | ||
| 329 | |||
| 330 | |||
| 331 | // Defaults for picture coding extension | ||
| 332 | |||
| 333 | priv->picture_coding_extension.extension_start_code = | ||
| 334 | MPEG2_START_EXTENSION; | ||
| 335 | priv->picture_coding_extension.extension_start_code_identifier = | ||
| 336 | MPEG2_EXTENSION_PICTURE_CODING; | ||
| 337 | |||
| 338 | pce->intra_dc_precision = 0; | ||
| 339 | pce->picture_structure = 3; | ||
| 340 | pce->top_field_first = 0; | ||
| 341 | pce->frame_pred_frame_dct = 1; | ||
| 342 | pce->concealment_motion_vectors = 0; | ||
| 343 | pce->q_scale_type = 0; | ||
| 344 | pce->intra_vlc_format = 0; | ||
| 345 | pce->alternate_scan = 0; | ||
| 346 | pce->repeat_first_field = 0; | ||
| 347 | pce->progressive_frame = 1; | ||
| 348 | pce->composite_display_flag = 0; | ||
| 349 | |||
| 350 | |||
| 351 | |||
| 352 | *vseq = (VAEncSequenceParameterBufferMPEG2) { | ||
| 353 | .intra_period = avctx->gop_size, | ||
| 354 | .ip_period = ctx->b_per_p + 1, | ||
| 355 | |||
| 356 | .picture_width = avctx->width, | ||
| 357 | .picture_height = avctx->height, | ||
| 358 | |||
| 359 | .bits_per_second = avctx->bit_rate, | ||
| 360 | .frame_rate = av_q2d(priv->frame_rate), | ||
| 361 | .aspect_ratio_information = sh->aspect_ratio_information, | ||
| 362 | .vbv_buffer_size = priv->vbv_buffer_size, | ||
| 363 | |||
| 364 | .sequence_extension.bits = { | ||
| 365 | .profile_and_level_indication = se->profile_and_level_indication, | ||
| 366 | .progressive_sequence = se->progressive_sequence, | ||
| 367 | .chroma_format = se->chroma_format, | ||
| 368 | .low_delay = se->low_delay, | ||
| 369 | .frame_rate_extension_n = se->frame_rate_extension_n, | ||
| 370 | .frame_rate_extension_d = se->frame_rate_extension_d, | ||
| 371 | }, | ||
| 372 | |||
| 373 | .new_gop_header = 1, | ||
| 374 | .gop_header.bits = { | ||
| 375 | .time_code = goph->time_code, | ||
| 376 | .closed_gop = goph->closed_gop, | ||
| 377 | .broken_link = goph->broken_link, | ||
| 378 | }, | ||
| 379 | }; | ||
| 380 | |||
| 381 | *vpic = (VAEncPictureParameterBufferMPEG2) { | ||
| 382 | .forward_reference_picture = VA_INVALID_ID, | ||
| 383 | .backward_reference_picture = VA_INVALID_ID, | ||
| 384 | .reconstructed_picture = VA_INVALID_ID, | ||
| 385 | .coded_buf = VA_INVALID_ID, | ||
| 386 | |||
| 387 | .vbv_delay = 0xffff, | ||
| 388 | .f_code = { { 15, 15 }, { 15, 15 } }, | ||
| 389 | |||
| 390 | .picture_coding_extension.bits = { | ||
| 391 | .intra_dc_precision = pce->intra_dc_precision, | ||
| 392 | .picture_structure = pce->picture_structure, | ||
| 393 | .top_field_first = pce->top_field_first, | ||
| 394 | .frame_pred_frame_dct = pce->frame_pred_frame_dct, | ||
| 395 | .concealment_motion_vectors = pce->concealment_motion_vectors, | ||
| 396 | .q_scale_type = pce->q_scale_type, | ||
| 397 | .intra_vlc_format = pce->intra_vlc_format, | ||
| 398 | .alternate_scan = pce->alternate_scan, | ||
| 399 | .repeat_first_field = pce->repeat_first_field, | ||
| 400 | .progressive_frame = pce->progressive_frame, | ||
| 401 | .composite_display_flag = pce->composite_display_flag, | ||
| 402 | }, | ||
| 403 | |||
| 404 | .composite_display.bits = { | ||
| 405 | .v_axis = pce->v_axis, | ||
| 406 | .field_sequence = pce->field_sequence, | ||
| 407 | .sub_carrier = pce->sub_carrier, | ||
| 408 | .burst_amplitude = pce->burst_amplitude, | ||
| 409 | .sub_carrier_phase = pce->sub_carrier_phase, | ||
| 410 | }, | ||
| 411 | }; | ||
| 255 | 412 | ||
| 256 | return 0; | 413 | return 0; |
| 257 | } | 414 | } |
| @@ -260,56 +417,61 @@ static int vaapi_encode_mpeg2_init_picture_params(AVCodecContext *avctx, · 2 unmodified lines | |||
| 260 | VAAPIEncodePicture *pic) | 417 | VAAPIEncodePicture *pic) |
| 261 | { | 418 | { |
| 262 | VAAPIEncodeContext *ctx = avctx->priv_data; | 419 | VAAPIEncodeContext *ctx = avctx->priv_data; |
| 263 | VAEncPictureParameterBufferMPEG2 *vpic = pic->codec_picture_params; | ||
| 264 | VAAPIEncodeMPEG2Context *priv = ctx->priv_data; | 420 | VAAPIEncodeMPEG2Context *priv = ctx->priv_data; |
| 265 | int fch, fcv; | 421 | MPEG2RawPictureHeader *ph = &priv->picture_header; |
| 422 | MPEG2RawPictureCodingExtension *pce = &priv->picture_coding_extension.data.picture_coding; | ||
| 423 | VAEncPictureParameterBufferMPEG2 *vpic = pic->codec_picture_params; | ||
| 266 | 424 | ||
| 267 | switch (avctx->level) { | 425 | if (pic->type == PICTURE_TYPE_IDR || pic->type == PICTURE_TYPE_I) { |
| 268 | case 4: // High. | 426 | ph->temporal_reference = 0; |
| 269 | case 6: // High 1440. | 427 | ph->picture_coding_type = 1; |
| 270 | fch = 9; | 428 | priv->last_i_frame = pic->display_order; |
| 271 | fcv = 5; | 429 | } else { |
| 272 | break; | 430 | ph->temporal_reference = pic->display_order - priv->last_i_frame; |
| 273 | case 8: // Main. | 431 | ph->picture_coding_type = pic->type == PICTURE_TYPE_B ? 3 : 2; |
| 274 | fch = 8; | 432 | } |
| 275 | fcv = 5; | 433 | |
| 276 | break; | 434 | if (pic->type == PICTURE_TYPE_P || pic->type == PICTURE_TYPE_B) { |
| 277 | case 10: // Low. | 435 | pce->f_code[0][0] = priv->f_code_horizontal; |
| 278 | default: | 436 | pce->f_code[0][1] = priv->f_code_vertical; |
| 279 | fch = 7; | 437 | } else { |
| 280 | fcv = 4; | 438 | pce->f_code[0][0] = 15; |
| 281 | break; | 439 | pce->f_code[0][1] = 15; |
| 440 | } | ||
| 441 | if (pic->type == PICTURE_TYPE_B) { | ||
| 442 | pce->f_code[1][0] = priv->f_code_horizontal; | ||
| 443 | pce->f_code[1][1] = priv->f_code_vertical; | ||
| 444 | } else { | ||
| 445 | pce->f_code[1][0] = 15; | ||
| 446 | pce->f_code[1][1] = 15; | ||
| 282 | } | 447 | } |
| 283 | 448 | ||
| 449 | vpic->reconstructed_picture = pic->recon_surface; | ||
| 450 | vpic->coded_buf = pic->output_buffer; | ||
| 451 | |||
| 284 | switch (pic->type) { | 452 | switch (pic->type) { |
| 285 | case PICTURE_TYPE_IDR: | 453 | case PICTURE_TYPE_IDR: |
| 286 | case PICTURE_TYPE_I: | 454 | case PICTURE_TYPE_I: |
| 287 | vpic->picture_type = VAEncPictureTypeIntra; | 455 | vpic->picture_type = VAEncPictureTypeIntra; |
| 288 | priv->last_i_frame = pic->display_order; | ||
| 289 | break; | 456 | break; |
| 290 | case PICTURE_TYPE_P: | 457 | case PICTURE_TYPE_P: |
| 291 | vpic->picture_type = VAEncPictureTypePredictive; | 458 | vpic->picture_type = VAEncPictureTypePredictive; |
| 292 | vpic->forward_reference_picture = pic->refs[0]->recon_surface; | 459 | vpic->forward_reference_picture = pic->refs[0]->recon_surface; |
| 293 | vpic->f_code[0][0] = fch; | ||
| 294 | vpic->f_code[0][1] = fcv; | ||
| 295 | break; | 460 | break; |
| 296 | case PICTURE_TYPE_B: | 461 | case PICTURE_TYPE_B: |
| 297 | vpic->picture_type = VAEncPictureTypeBidirectional; | 462 | vpic->picture_type = VAEncPictureTypeBidirectional; |
| 298 | vpic->forward_reference_picture = pic->refs[0]->recon_surface; | 463 | vpic->forward_reference_picture = pic->refs[0]->recon_surface; |
| 299 | vpic->backward_reference_picture = pic->refs[1]->recon_surface; | 464 | vpic->backward_reference_picture = pic->refs[1]->recon_surface; |
| 300 | vpic->f_code[0][0] = fch; | ||
| 301 | vpic->f_code[0][1] = fcv; | ||
| 302 | vpic->f_code[1][0] = fch; | ||
| 303 | vpic->f_code[1][1] = fcv; | ||
| 304 | break; | 465 | break; |
| 305 | default: | 466 | default: |
| 306 | av_assert0(0 && "invalid picture type"); | 467 | av_assert0(0 && "invalid picture type"); |
| 307 | } | 468 | } |
| 308 | 469 | ||
| 309 | vpic->reconstructed_picture = pic->recon_surface; | 470 | vpic->temporal_reference = ph->temporal_reference; |
| 310 | vpic->coded_buf = pic->output_buffer; | 471 | vpic->f_code[0][0] = pce->f_code[0][0]; |
| 311 | 472 | vpic->f_code[0][1] = pce->f_code[0][1]; | |
| 312 | vpic->temporal_reference = pic->display_order - priv->last_i_frame; | 473 | vpic->f_code[1][0] = pce->f_code[1][0]; |
| 474 | vpic->f_code[1][1] = pce->f_code[1][1]; | ||
| 313 | 475 | ||
| 314 | pic->nb_slices = priv->mb_height; | 476 | pic->nb_slices = priv->mb_height; |
| 315 | 477 | ||
| @@ -354,6 +516,11 @@ static av_cold int vaapi_encode_mpeg2_configure(AVCodecContext *avctx) · 38 unmodified lines | |||
| 354 | { | 516 | { |
| 355 | VAAPIEncodeContext *ctx = avctx->priv_data; | 517 | VAAPIEncodeContext *ctx = avctx->priv_data; |
| 356 | VAAPIEncodeMPEG2Context *priv = ctx->priv_data; | 518 | VAAPIEncodeMPEG2Context *priv = ctx->priv_data; |
| 519 | int err; | ||
| 520 | |||
| 521 | err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_MPEG2VIDEO, avctx); | ||
| 522 | if (err < 0) | ||
| 523 | return err; | ||
| 357 | 524 | ||
| 358 | priv->mb_width = FFALIGN(avctx->width, 16) / 16; | 525 | priv->mb_width = FFALIGN(avctx->width, 16) / 16; |
| 359 | priv->mb_height = FFALIGN(avctx->height, 16) / 16; | 526 | priv->mb_height = FFALIGN(avctx->height, 16) / 16; |
| @@ -420,11 +587,41 @@ static av_cold int vaapi_encode_mpeg2_init(AVCodecContext *avctx) · 60 unmodified lines | |||
| 420 | case FF_PROFILE_MPEG2_MAIN: | 587 | case FF_PROFILE_MPEG2_MAIN: |
| 421 | ctx->va_profile = VAProfileMPEG2Main; | 588 | ctx->va_profile = VAProfileMPEG2Main; |
| 422 | break; | 589 | break; |
| 590 | case FF_PROFILE_MPEG2_422: | ||
| 591 | av_log(avctx, AV_LOG_ERROR, "MPEG-2 4:2:2 profile " | ||
| 592 | "is not supported.\n"); | ||
| 593 | return AVERROR_PATCHWELCOME; | ||
| 594 | case FF_PROFILE_MPEG2_HIGH: | ||
| 595 | av_log(avctx, AV_LOG_ERROR, "MPEG-2 high profile " | ||
| 596 | "is not supported.\n"); | ||
| 597 | return AVERROR_PATCHWELCOME; | ||
| 598 | case FF_PROFILE_MPEG2_SS: | ||
| 599 | case FF_PROFILE_MPEG2_SNR_SCALABLE: | ||
| 600 | av_log(avctx, AV_LOG_ERROR, "MPEG-2 scalable profiles " | ||
| 601 | "are not supported.\n"); | ||
| 602 | return AVERROR_PATCHWELCOME; | ||
| 423 | default: | 603 | default: |
| 424 | av_log(avctx, AV_LOG_ERROR, "Unknown MPEG-2 profile %d.\n", | 604 | av_log(avctx, AV_LOG_ERROR, "Unknown MPEG-2 profile %d.\n", |
| 425 | avctx->profile); | 605 | avctx->profile); |
| 426 | return AVERROR(EINVAL); | 606 | return AVERROR(EINVAL); |
| 427 | } | 607 | } |
| 608 | switch (avctx->level) { | ||
| 609 | case 4: // High | ||
| 610 | case 6: // High 1440 | ||
| 611 | case 8: // Main | ||
| 612 | case 10: // Low | ||
| 613 | break; | ||
| 614 | default: | ||
| 615 | av_log(avctx, AV_LOG_ERROR, "Unknown MPEG-2 level %d.\n", | ||
| 616 | avctx->level); | ||
| 617 | return AVERROR(EINVAL); | ||
| 618 | } | ||
| 619 | |||
| 620 | if (avctx->height % 4096 == 0 || avctx->width % 4096 == 0) { | ||
| 621 | av_log(avctx, AV_LOG_ERROR, "MPEG-2 does not support picture " | ||
| 622 | "height or width divisible by 4096.\n"); | ||
| 623 | return AVERROR(EINVAL); | ||
| 624 | } | ||
| 428 | 625 | ||
| 429 | ctx->va_entrypoint = VAEntrypointEncSlice; | 626 | ctx->va_entrypoint = VAEntrypointEncSlice; |
| 430 | ctx->va_rt_format = VA_RT_FORMAT_YUV420; | 627 | ctx->va_rt_format = VA_RT_FORMAT_YUV420; |
| @@ -439,6 +636,17 @@ static av_cold int vaapi_encode_mpeg2_init(AVCodecContext *avctx) · 8 unmodified lines | |||
| 439 | return ff_vaapi_encode_init(avctx); | 636 | return ff_vaapi_encode_init(avctx); |
| 440 | } | 637 | } |
| 441 | 638 | ||
| 639 | static av_cold int vaapi_encode_mpeg2_close(AVCodecContext *avctx) | ||
| 640 | { | ||
| 641 | VAAPIEncodeContext *ctx = avctx->priv_data; | ||
| 642 | VAAPIEncodeMPEG2Context *priv = ctx->priv_data; | ||
| 643 | |||
| 644 | if (priv) | ||
| 645 | ff_cbs_close(&priv->cbc); | ||
| 646 | |||
| 647 | return ff_vaapi_encode_close(avctx); | ||
| 648 | } | ||
| 649 | |||
| 442 | static const AVCodecDefault vaapi_encode_mpeg2_defaults[] = { | 650 | static const AVCodecDefault vaapi_encode_mpeg2_defaults[] = { |
| 443 | { "profile", "4" }, | 651 | { "profile", "4" }, |
| 444 | { "level", "4" }, | 652 | { "level", "4" }, |
| @@ -460,7 +668,7 @@ AVCodec ff_mpeg2_vaapi_encoder = { · 15 unmodified lines | |||
| 460 | .priv_data_size = sizeof(VAAPIEncodeContext), | 668 | .priv_data_size = sizeof(VAAPIEncodeContext), |
| 461 | .init = &vaapi_encode_mpeg2_init, | 669 | .init = &vaapi_encode_mpeg2_init, |
| 462 | .encode2 = &ff_vaapi_encode2, | 670 | .encode2 = &ff_vaapi_encode2, |
| 463 | .close = &ff_vaapi_encode_close, | 671 | .close = &vaapi_encode_mpeg2_close, |
| 464 | .capabilities = AV_CODEC_CAP_DELAY, | 672 | .capabilities = AV_CODEC_CAP_DELAY, |
| 465 | .defaults = vaapi_encode_mpeg2_defaults, | 673 | .defaults = vaapi_encode_mpeg2_defaults, |
| 466 | .pix_fmts = (const enum AVPixelFormat[]) { | 674 | .pix_fmts = (const enum AVPixelFormat[]) { |