1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2019 BayLibre, SAS 4 * Author: Maxime Jourdan <mjourdan@baylibre.com> 5 */ 6 7#include <media/v4l2-mem2mem.h> 8#include <media/videobuf2-dma-contig.h> 9 10#include "vdec_helpers.h" 11#include "dos_regs.h" 12#include "codec_h264.h" 13 14#define SIZE_EXT_FW (20 * SZ_1K) 15#define SIZE_WORKSPACE 0x1ee000 16#define SIZE_SEI (8 * SZ_1K) 17 18/* 19 * Offset added by the firmware which must be substracted 20 * from the workspace phyaddr 21 */ 22#define WORKSPACE_BUF_OFFSET 0x1000000 23 24/* ISR status */ 25#define CMD_MASK GENMASK(7, 0) 26#define CMD_SRC_CHANGE 1 27#define CMD_FRAMES_READY 2 28#define CMD_FATAL_ERROR 6 29#define CMD_BAD_WIDTH 7 30#define CMD_BAD_HEIGHT 8 31 32#define SEI_DATA_READY BIT(15) 33 34/* Picture type */ 35#define PIC_TOP_BOT 5 36#define PIC_BOT_TOP 6 37 38/* Size of Motion Vector per macroblock */ 39#define MB_MV_SIZE 96 40 41/* Frame status data */ 42#define PIC_STRUCT_BIT 5 43#define PIC_STRUCT_MASK GENMASK(2, 0) 44#define BUF_IDX_MASK GENMASK(4, 0) 45#define ERROR_FLAG BIT(9) 46#define OFFSET_BIT 16 47#define OFFSET_MASK GENMASK(15, 0) 48 49/* Bitstream parsed data */ 50#define MB_TOTAL_BIT 8 51#define MB_TOTAL_MASK GENMASK(15, 0) 52#define MB_WIDTH_MASK GENMASK(7, 0) 53#define MAX_REF_BIT 24 54#define MAX_REF_MASK GENMASK(6, 0) 55#define AR_IDC_BIT 16 56#define AR_IDC_MASK GENMASK(7, 0) 57#define AR_PRESENT_FLAG BIT(0) 58#define AR_EXTEND 0xff 59 60/* 61 * Buffer to send to the ESPARSER to signal End Of Stream for H.264. 62 * This is a 16x16 encoded picture that will trigger drain firmware-side. 63 * There is no known alternative. 64 */ 65static const u8 eos_sequence[SZ_4K] = { 66 0x00, 0x00, 0x00, 0x01, 0x06, 0x05, 0xff, 0xe4, 0xdc, 0x45, 0xe9, 0xbd, 67 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee, 0xef, 68 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x20, 69 0x36, 0x37, 0x20, 0x72, 0x31, 0x31, 0x33, 0x30, 0x20, 0x38, 0x34, 0x37, 70 0x35, 0x39, 0x37, 0x37, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 71 0x2f, 0x4d, 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 72 0x63, 0x6f, 0x64, 0x65, 0x63, 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 73 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x30, 74 0x30, 0x39, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 75 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 76 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 77 0x6d, 0x6c, 0x20, 0x2d, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 78 0x3a, 0x20, 0x63, 0x61, 0x62, 0x61, 0x63, 0x3d, 0x31, 0x20, 0x72, 0x65, 79 0x66, 0x3d, 0x31, 0x20, 0x64, 0x65, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3d, 80 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 81 0x65, 0x3d, 0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 82 0x6d, 0x65, 0x3d, 0x68, 0x65, 0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 83 0x3d, 0x36, 0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 84 0x30, 0x3a, 0x30, 0x2e, 0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 85 0x72, 0x65, 0x66, 0x3d, 0x30, 0x20, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 86 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 87 0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69, 88 0x73, 0x3d, 0x30, 0x20, 0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 89 0x20, 0x63, 0x71, 0x6d, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x61, 0x64, 0x7a, 90 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31, 0x2c, 0x31, 0x31, 0x20, 0x63, 0x68, 91 0x72, 0x6f, 0x6d, 0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66, 0x73, 92 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 93 0x73, 0x3d, 0x31, 0x20, 0x6e, 0x72, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x63, 94 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x6d, 0x62, 0x61, 0x66, 95 0x66, 0x3d, 0x30, 0x20, 0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 96 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30, 97 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 98 0x32, 0x35, 0x20, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x63, 0x75, 0x74, 0x3d, 99 0x34, 0x30, 0x20, 0x72, 0x63, 0x3d, 0x61, 0x62, 0x72, 0x20, 0x62, 0x69, 100 0x74, 0x72, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x30, 0x20, 0x72, 0x61, 0x74, 101 0x65, 0x74, 0x6f, 0x6c, 0x3d, 0x31, 0x2e, 0x30, 0x20, 0x71, 0x63, 0x6f, 102 0x6d, 0x70, 0x3d, 0x30, 0x2e, 0x36, 0x30, 0x20, 0x71, 0x70, 0x6d, 0x69, 103 0x6e, 0x3d, 0x31, 0x30, 0x20, 0x71, 0x70, 0x6d, 0x61, 0x78, 0x3d, 0x35, 104 0x31, 0x20, 0x71, 0x70, 0x73, 0x74, 0x65, 0x70, 0x3d, 0x34, 0x20, 0x69, 105 0x70, 0x5f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x3d, 0x31, 0x2e, 0x34, 0x30, 106 0x20, 0x61, 0x71, 0x3d, 0x31, 0x3a, 0x31, 0x2e, 0x30, 0x30, 0x00, 0x80, 107 0x00, 0x00, 0x00, 0x01, 0x67, 0x4d, 0x40, 0x0a, 0x9a, 0x74, 0xf4, 0x20, 108 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x06, 0x51, 0xe2, 0x44, 0xd4, 109 0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x32, 0xc8, 0x00, 0x00, 0x00, 0x01, 110 0x65, 0x88, 0x80, 0x20, 0x00, 0x08, 0x7f, 0xea, 0x6a, 0xe2, 0x99, 0xb6, 111 0x57, 0xae, 0x49, 0x30, 0xf5, 0xfe, 0x5e, 0x46, 0x0b, 0x72, 0x44, 0xc4, 112 0xe1, 0xfc, 0x62, 0xda, 0xf1, 0xfb, 0xa2, 0xdb, 0xd6, 0xbe, 0x5c, 0xd7, 113 0x24, 0xa3, 0xf5, 0xb9, 0x2f, 0x57, 0x16, 0x49, 0x75, 0x47, 0x77, 0x09, 114 0x5c, 0xa1, 0xb4, 0xc3, 0x4f, 0x60, 0x2b, 0xb0, 0x0c, 0xc8, 0xd6, 0x66, 115 0xba, 0x9b, 0x82, 0x29, 0x33, 0x92, 0x26, 0x99, 0x31, 0x1c, 0x7f, 0x9b, 116 0x00, 0x00, 0x01, 0x0ff, 117}; 118 119static const u8 *codec_h264_eos_sequence(u32 *len) 120{ 121 *len = ARRAY_SIZE(eos_sequence); 122 return eos_sequence; 123} 124 125struct codec_h264 { 126 /* H.264 decoder requires an extended firmware */ 127 void *ext_fw_vaddr; 128 dma_addr_t ext_fw_paddr; 129 130 /* Buffer for the H.264 Workspace */ 131 void *workspace_vaddr; 132 dma_addr_t workspace_paddr; 133 134 /* Buffer for the H.264 references MV */ 135 void *ref_vaddr; 136 dma_addr_t ref_paddr; 137 u32 ref_size; 138 139 /* Buffer for parsed SEI data */ 140 void *sei_vaddr; 141 dma_addr_t sei_paddr; 142 143 u32 mb_width; 144 u32 mb_height; 145 u32 max_refs; 146}; 147 148static int codec_h264_can_recycle(struct amvdec_core *core) 149{ 150 return !amvdec_read_dos(core, AV_SCRATCH_7) || 151 !amvdec_read_dos(core, AV_SCRATCH_8); 152} 153 154static void codec_h264_recycle(struct amvdec_core *core, u32 buf_idx) 155{ 156 /* 157 * Tell the firmware it can recycle this buffer. 158 * AV_SCRATCH_8 serves the same purpose. 159 */ 160 if (!amvdec_read_dos(core, AV_SCRATCH_7)) 161 amvdec_write_dos(core, AV_SCRATCH_7, buf_idx + 1); 162 else 163 amvdec_write_dos(core, AV_SCRATCH_8, buf_idx + 1); 164} 165 166static int codec_h264_start(struct amvdec_session *sess) 167{ 168 u32 workspace_offset; 169 struct amvdec_core *core = sess->core; 170 struct codec_h264 *h264 = sess->priv; 171 172 /* Allocate some memory for the H.264 decoder's state */ 173 h264->workspace_vaddr = 174 dma_alloc_coherent(core->dev, SIZE_WORKSPACE, 175 &h264->workspace_paddr, GFP_KERNEL); 176 if (!h264->workspace_vaddr) 177 return -ENOMEM; 178 179 /* Allocate some memory for the H.264 SEI dump */ 180 h264->sei_vaddr = dma_alloc_coherent(core->dev, SIZE_SEI, 181 &h264->sei_paddr, GFP_KERNEL); 182 if (!h264->sei_vaddr) 183 return -ENOMEM; 184 185 amvdec_write_dos_bits(core, POWER_CTL_VLD, BIT(9) | BIT(6)); 186 187 workspace_offset = h264->workspace_paddr - WORKSPACE_BUF_OFFSET; 188 amvdec_write_dos(core, AV_SCRATCH_1, workspace_offset); 189 amvdec_write_dos(core, AV_SCRATCH_G, h264->ext_fw_paddr); 190 amvdec_write_dos(core, AV_SCRATCH_I, h264->sei_paddr - 191 workspace_offset); 192 193 /* Enable "error correction" */ 194 amvdec_write_dos(core, AV_SCRATCH_F, 195 (amvdec_read_dos(core, AV_SCRATCH_F) & 0xffffffc3) | 196 BIT(4) | BIT(7)); 197 198 amvdec_write_dos(core, MDEC_PIC_DC_THRESH, 0x404038aa); 199 200 return 0; 201} 202 203static int codec_h264_stop(struct amvdec_session *sess) 204{ 205 struct codec_h264 *h264 = sess->priv; 206 struct amvdec_core *core = sess->core; 207 208 if (h264->ext_fw_vaddr) 209 dma_free_coherent(core->dev, SIZE_EXT_FW, 210 h264->ext_fw_vaddr, h264->ext_fw_paddr); 211 212 if (h264->workspace_vaddr) 213 dma_free_coherent(core->dev, SIZE_WORKSPACE, 214 h264->workspace_vaddr, h264->workspace_paddr); 215 216 if (h264->ref_vaddr) 217 dma_free_coherent(core->dev, h264->ref_size, 218 h264->ref_vaddr, h264->ref_paddr); 219 220 if (h264->sei_vaddr) 221 dma_free_coherent(core->dev, SIZE_SEI, 222 h264->sei_vaddr, h264->sei_paddr); 223 224 return 0; 225} 226 227static int codec_h264_load_extended_firmware(struct amvdec_session *sess, 228 const u8 *data, u32 len) 229{ 230 struct codec_h264 *h264; 231 struct amvdec_core *core = sess->core; 232 233 if (len < SIZE_EXT_FW) 234 return -EINVAL; 235 236 h264 = kzalloc(sizeof(*h264), GFP_KERNEL); 237 if (!h264) 238 return -ENOMEM; 239 240 h264->ext_fw_vaddr = dma_alloc_coherent(core->dev, SIZE_EXT_FW, 241 &h264->ext_fw_paddr, 242 GFP_KERNEL); 243 if (!h264->ext_fw_vaddr) { 244 kfree(h264); 245 return -ENOMEM; 246 } 247 248 memcpy(h264->ext_fw_vaddr, data, SIZE_EXT_FW); 249 sess->priv = h264; 250 251 return 0; 252} 253 254static const struct v4l2_fract par_table[] = { 255 { 1, 1 }, { 1, 1 }, { 12, 11 }, { 10, 11 }, 256 { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 }, 257 { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 }, 258 { 64, 33 }, { 160, 99 }, { 4, 3 }, { 3, 2 }, 259 { 2, 1 } 260}; 261 262static void codec_h264_set_par(struct amvdec_session *sess) 263{ 264 struct amvdec_core *core = sess->core; 265 u32 seq_info = amvdec_read_dos(core, AV_SCRATCH_2); 266 u32 ar_idc = (seq_info >> AR_IDC_BIT) & AR_IDC_MASK; 267 268 if (!(seq_info & AR_PRESENT_FLAG)) 269 return; 270 271 if (ar_idc == AR_EXTEND) { 272 u32 ar_info = amvdec_read_dos(core, AV_SCRATCH_3); 273 274 sess->pixelaspect.numerator = ar_info & 0xffff; 275 sess->pixelaspect.denominator = (ar_info >> 16) & 0xffff; 276 return; 277 } 278 279 if (ar_idc >= ARRAY_SIZE(par_table)) 280 return; 281 282 sess->pixelaspect = par_table[ar_idc]; 283} 284 285static void codec_h264_resume(struct amvdec_session *sess) 286{ 287 struct amvdec_core *core = sess->core; 288 struct codec_h264 *h264 = sess->priv; 289 u32 mb_width, mb_height, mb_total; 290 291 amvdec_set_canvases(sess, 292 (u32[]){ ANC0_CANVAS_ADDR, 0 }, 293 (u32[]){ 24, 0 }); 294 295 dev_dbg(core->dev, "max_refs = %u; actual_dpb_size = %u\n", 296 h264->max_refs, sess->num_dst_bufs); 297 298 /* Align to a multiple of 4 macroblocks */ 299 mb_width = ALIGN(h264->mb_width, 4); 300 mb_height = ALIGN(h264->mb_height, 4); 301 mb_total = mb_width * mb_height; 302 303 h264->ref_size = mb_total * MB_MV_SIZE * h264->max_refs; 304 h264->ref_vaddr = dma_alloc_coherent(core->dev, h264->ref_size, 305 &h264->ref_paddr, GFP_KERNEL); 306 if (!h264->ref_vaddr) { 307 amvdec_abort(sess); 308 return; 309 } 310 311 /* Address to store the references' MVs */ 312 amvdec_write_dos(core, AV_SCRATCH_1, h264->ref_paddr); 313 /* End of ref MV */ 314 amvdec_write_dos(core, AV_SCRATCH_4, h264->ref_paddr + h264->ref_size); 315 316 amvdec_write_dos(core, AV_SCRATCH_0, (h264->max_refs << 24) | 317 (sess->num_dst_bufs << 16) | 318 ((h264->max_refs - 1) << 8)); 319} 320 321/* 322 * Configure the H.264 decoder when the parser detected a parameter set change 323 */ 324static void codec_h264_src_change(struct amvdec_session *sess) 325{ 326 struct amvdec_core *core = sess->core; 327 struct codec_h264 *h264 = sess->priv; 328 u32 parsed_info, mb_total; 329 u32 crop_infor, crop_bottom, crop_right; 330 u32 frame_width, frame_height; 331 332 sess->keyframe_found = 1; 333 334 parsed_info = amvdec_read_dos(core, AV_SCRATCH_1); 335 336 /* Total number of 16x16 macroblocks */ 337 mb_total = (parsed_info >> MB_TOTAL_BIT) & MB_TOTAL_MASK; 338 /* Number of macroblocks per line */ 339 h264->mb_width = parsed_info & MB_WIDTH_MASK; 340 /* Number of macroblock lines */ 341 h264->mb_height = mb_total / h264->mb_width; 342 343 h264->max_refs = ((parsed_info >> MAX_REF_BIT) & MAX_REF_MASK) + 1; 344 345 crop_infor = amvdec_read_dos(core, AV_SCRATCH_6); 346 crop_bottom = (crop_infor & 0xff); 347 crop_right = (crop_infor >> 16) & 0xff; 348 349 frame_width = h264->mb_width * 16 - crop_right; 350 frame_height = h264->mb_height * 16 - crop_bottom; 351 352 dev_dbg(core->dev, "frame: %ux%u; crop: %u %u\n", 353 frame_width, frame_height, crop_right, crop_bottom); 354 355 codec_h264_set_par(sess); 356 amvdec_src_change(sess, frame_width, frame_height, h264->max_refs + 5); 357} 358 359/* 360 * The bitstream offset is split in half in 2 different registers. 361 * Fetch its MSB here, which location depends on the frame number. 362 */ 363static u32 get_offset_msb(struct amvdec_core *core, int frame_num) 364{ 365 int take_msb = frame_num % 2; 366 int reg_offset = (frame_num / 2) * 4; 367 u32 offset_msb = amvdec_read_dos(core, AV_SCRATCH_A + reg_offset); 368 369 if (take_msb) 370 return offset_msb & 0xffff0000; 371 372 return (offset_msb & 0x0000ffff) << 16; 373} 374 375static void codec_h264_frames_ready(struct amvdec_session *sess, u32 status) 376{ 377 struct amvdec_core *core = sess->core; 378 int error_count; 379 int num_frames; 380 int i; 381 382 error_count = amvdec_read_dos(core, AV_SCRATCH_D); 383 num_frames = (status >> 8) & 0xff; 384 if (error_count) { 385 dev_warn(core->dev, 386 "decoder error(s) happened, count %d\n", error_count); 387 amvdec_write_dos(core, AV_SCRATCH_D, 0); 388 } 389 390 for (i = 0; i < num_frames; i++) { 391 u32 frame_status = amvdec_read_dos(core, AV_SCRATCH_1 + i * 4); 392 u32 buffer_index = frame_status & BUF_IDX_MASK; 393 u32 pic_struct = (frame_status >> PIC_STRUCT_BIT) & 394 PIC_STRUCT_MASK; 395 u32 offset = (frame_status >> OFFSET_BIT) & OFFSET_MASK; 396 u32 field = V4L2_FIELD_NONE; 397 398 /* 399 * A buffer decode error means it was decoded, 400 * but part of the picture will have artifacts. 401 * Typical reason is a temporarily corrupted bitstream 402 */ 403 if (frame_status & ERROR_FLAG) 404 dev_dbg(core->dev, "Buffer %d decode error\n", 405 buffer_index); 406 407 if (pic_struct == PIC_TOP_BOT) 408 field = V4L2_FIELD_INTERLACED_TB; 409 else if (pic_struct == PIC_BOT_TOP) 410 field = V4L2_FIELD_INTERLACED_BT; 411 412 offset |= get_offset_msb(core, i); 413 amvdec_dst_buf_done_idx(sess, buffer_index, offset, field); 414 } 415} 416 417static irqreturn_t codec_h264_threaded_isr(struct amvdec_session *sess) 418{ 419 struct amvdec_core *core = sess->core; 420 u32 status; 421 u32 size; 422 u8 cmd; 423 424 status = amvdec_read_dos(core, AV_SCRATCH_0); 425 cmd = status & CMD_MASK; 426 427 switch (cmd) { 428 case CMD_SRC_CHANGE: 429 codec_h264_src_change(sess); 430 break; 431 case CMD_FRAMES_READY: 432 codec_h264_frames_ready(sess, status); 433 break; 434 case CMD_FATAL_ERROR: 435 dev_err(core->dev, "H.264 decoder fatal error\n"); 436 goto abort; 437 case CMD_BAD_WIDTH: 438 size = (amvdec_read_dos(core, AV_SCRATCH_1) + 1) * 16; 439 dev_err(core->dev, "Unsupported video width: %u\n", size); 440 goto abort; 441 case CMD_BAD_HEIGHT: 442 size = (amvdec_read_dos(core, AV_SCRATCH_1) + 1) * 16; 443 dev_err(core->dev, "Unsupported video height: %u\n", size); 444 goto abort; 445 case 0: /* Unused but not worth printing for */ 446 case 9: 447 break; 448 default: 449 dev_info(core->dev, "Unexpected H264 ISR: %08X\n", cmd); 450 break; 451 } 452 453 if (cmd && cmd != CMD_SRC_CHANGE) 454 amvdec_write_dos(core, AV_SCRATCH_0, 0); 455 456 /* Decoder has some SEI data for us ; ignore */ 457 if (amvdec_read_dos(core, AV_SCRATCH_J) & SEI_DATA_READY) 458 amvdec_write_dos(core, AV_SCRATCH_J, 0); 459 460 return IRQ_HANDLED; 461abort: 462 amvdec_abort(sess); 463 return IRQ_HANDLED; 464} 465 466static irqreturn_t codec_h264_isr(struct amvdec_session *sess) 467{ 468 struct amvdec_core *core = sess->core; 469 470 amvdec_write_dos(core, ASSIST_MBOX1_CLR_REG, 1); 471 472 return IRQ_WAKE_THREAD; 473} 474 475struct amvdec_codec_ops codec_h264_ops = { 476 .start = codec_h264_start, 477 .stop = codec_h264_stop, 478 .load_extended_firmware = codec_h264_load_extended_firmware, 479 .isr = codec_h264_isr, 480 .threaded_isr = codec_h264_threaded_isr, 481 .can_recycle = codec_h264_can_recycle, 482 .recycle = codec_h264_recycle, 483 .eos_sequence = codec_h264_eos_sequence, 484 .resume = codec_h264_resume, 485}; 486