4 * Copyright (C) 2012 - 2013 Guillaume Martres
5 * Copyright (C) 2012 - 2013 Gildas Cocherel
7 * This file is part of Libav.
9 * Libav is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * Libav is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with Libav; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "libavutil/avassert.h"
25 #include "libavutil/pixdesc.h"
32 void ff_hevc_unref_frame(HEVCContext
*s
, HEVCFrame
*frame
, int flags
)
34 /* frame->frame can be NULL if context init failed */
35 if (!frame
->frame
|| !frame
->frame
->buf
[0])
38 frame
->flags
&= ~flags
;
40 ff_thread_release_buffer(s
->avctx
, &frame
->tf
);
42 av_buffer_unref(&frame
->tab_mvf_buf
);
43 frame
->tab_mvf
= NULL
;
45 av_buffer_unref(&frame
->rpl_buf
);
46 av_buffer_unref(&frame
->rpl_tab_buf
);
47 frame
->rpl_tab
= NULL
;
48 frame
->refPicList
= NULL
;
50 frame
->collocated_ref
= NULL
;
52 av_buffer_unref(&frame
->hwaccel_priv_buf
);
53 frame
->hwaccel_picture_private
= NULL
;
57 RefPicList
*ff_hevc_get_ref_list(HEVCContext
*s
, HEVCFrame
*ref
, int x0
, int y0
)
59 int x_cb
= x0
>> s
->ps
.sps
->log2_ctb_size
;
60 int y_cb
= y0
>> s
->ps
.sps
->log2_ctb_size
;
61 int pic_width_cb
= (s
->ps
.sps
->width
+ (1 << s
->ps
.sps
->log2_ctb_size
) - 1) >>
62 s
->ps
.sps
->log2_ctb_size
;
63 int ctb_addr_ts
= s
->ps
.pps
->ctb_addr_rs_to_ts
[y_cb
* pic_width_cb
+ x_cb
];
64 return (RefPicList
*)ref
->rpl_tab
[ctb_addr_ts
];
67 void ff_hevc_clear_refs(HEVCContext
*s
)
70 for (i
= 0; i
< FF_ARRAY_ELEMS(s
->DPB
); i
++)
71 ff_hevc_unref_frame(s
, &s
->DPB
[i
],
72 HEVC_FRAME_FLAG_SHORT_REF
|
73 HEVC_FRAME_FLAG_LONG_REF
);
76 void ff_hevc_flush_dpb(HEVCContext
*s
)
79 for (i
= 0; i
< FF_ARRAY_ELEMS(s
->DPB
); i
++)
80 ff_hevc_unref_frame(s
, &s
->DPB
[i
], ~0);
83 static HEVCFrame
*alloc_frame(HEVCContext
*s
)
86 for (i
= 0; i
< FF_ARRAY_ELEMS(s
->DPB
); i
++) {
87 HEVCFrame
*frame
= &s
->DPB
[i
];
88 if (frame
->frame
->buf
[0])
91 ret
= ff_thread_get_buffer(s
->avctx
, &frame
->tf
,
92 AV_GET_BUFFER_FLAG_REF
);
96 frame
->rpl_buf
= av_buffer_allocz(s
->pkt
.nb_nals
* sizeof(RefPicListTab
));
100 frame
->tab_mvf_buf
= av_buffer_pool_get(s
->tab_mvf_pool
);
101 if (!frame
->tab_mvf_buf
)
103 frame
->tab_mvf
= (MvField
*)frame
->tab_mvf_buf
->data
;
105 frame
->rpl_tab_buf
= av_buffer_pool_get(s
->rpl_tab_pool
);
106 if (!frame
->rpl_tab_buf
)
108 frame
->rpl_tab
= (RefPicListTab
**)frame
->rpl_tab_buf
->data
;
109 frame
->ctb_count
= s
->ps
.sps
->ctb_width
* s
->ps
.sps
->ctb_height
;
110 for (j
= 0; j
< frame
->ctb_count
; j
++)
111 frame
->rpl_tab
[j
] = (RefPicListTab
*)frame
->rpl_buf
->data
;
113 if (s
->avctx
->hwaccel
) {
114 const AVHWAccel
*hwaccel
= s
->avctx
->hwaccel
;
115 av_assert0(!frame
->hwaccel_picture_private
);
116 if (hwaccel
->frame_priv_data_size
) {
117 frame
->hwaccel_priv_buf
= av_buffer_allocz(hwaccel
->frame_priv_data_size
);
118 if (!frame
->hwaccel_priv_buf
)
120 frame
->hwaccel_picture_private
= frame
->hwaccel_priv_buf
->data
;
127 ff_hevc_unref_frame(s
, frame
, ~0);
130 av_log(s
->avctx
, AV_LOG_ERROR
, "Error allocating frame, DPB full.\n");
134 int ff_hevc_set_new_ref(HEVCContext
*s
, AVFrame
**frame
, int poc
)
139 /* check that this POC doesn't already exist */
140 for (i
= 0; i
< FF_ARRAY_ELEMS(s
->DPB
); i
++) {
141 HEVCFrame
*frame
= &s
->DPB
[i
];
143 if (frame
->frame
->buf
[0] && frame
->sequence
== s
->seq_decode
&&
145 av_log(s
->avctx
, AV_LOG_ERROR
, "Duplicate POC in a sequence: %d.\n",
147 return AVERROR_INVALIDDATA
;
151 ref
= alloc_frame(s
);
153 return AVERROR(ENOMEM
);
158 if (s
->sh
.pic_output_flag
)
159 ref
->flags
= HEVC_FRAME_FLAG_OUTPUT
| HEVC_FRAME_FLAG_SHORT_REF
;
161 ref
->flags
= HEVC_FRAME_FLAG_SHORT_REF
;
164 ref
->sequence
= s
->seq_decode
;
165 ref
->frame
->crop_left
= s
->ps
.sps
->output_window
.left_offset
;
166 ref
->frame
->crop_right
= s
->ps
.sps
->output_window
.right_offset
;
167 ref
->frame
->crop_top
= s
->ps
.sps
->output_window
.top_offset
;
168 ref
->frame
->crop_bottom
= s
->ps
.sps
->output_window
.bottom_offset
;
173 int ff_hevc_output_frame(HEVCContext
*s
, AVFrame
*out
, int flush
)
177 int min_poc
= INT_MAX
;
180 for (i
= 0; i
< FF_ARRAY_ELEMS(s
->DPB
); i
++) {
181 HEVCFrame
*frame
= &s
->DPB
[i
];
182 if ((frame
->flags
& HEVC_FRAME_FLAG_OUTPUT
) &&
183 frame
->sequence
== s
->seq_output
) {
185 if (frame
->poc
< min_poc
) {
186 min_poc
= frame
->poc
;
192 /* wait for more frames before output */
193 if (!flush
&& s
->seq_output
== s
->seq_decode
&& s
->ps
.sps
&&
194 nb_output
<= s
->ps
.sps
->temporal_layer
[s
->ps
.sps
->max_sub_layers
- 1].num_reorder_pics
)
198 HEVCFrame
*frame
= &s
->DPB
[min_idx
];
200 ret
= av_frame_ref(out
, frame
->frame
);
201 ff_hevc_unref_frame(s
, frame
, HEVC_FRAME_FLAG_OUTPUT
);
205 av_log(s
->avctx
, AV_LOG_DEBUG
,
206 "Output frame with POC %d.\n", frame
->poc
);
210 if (s
->seq_output
!= s
->seq_decode
)
211 s
->seq_output
= (s
->seq_output
+ 1) & 0xff;
219 static int init_slice_rpl(HEVCContext
*s
)
221 HEVCFrame
*frame
= s
->ref
;
222 int ctb_count
= frame
->ctb_count
;
223 int ctb_addr_ts
= s
->ps
.pps
->ctb_addr_rs_to_ts
[s
->sh
.slice_segment_addr
];
226 if (s
->slice_idx
>= frame
->rpl_buf
->size
/ sizeof(RefPicListTab
))
227 return AVERROR_INVALIDDATA
;
229 for (i
= ctb_addr_ts
; i
< ctb_count
; i
++)
230 frame
->rpl_tab
[i
] = (RefPicListTab
*)frame
->rpl_buf
->data
+ s
->slice_idx
;
232 frame
->refPicList
= (RefPicList
*)frame
->rpl_tab
[ctb_addr_ts
];
237 int ff_hevc_slice_rpl(HEVCContext
*s
)
239 SliceHeader
*sh
= &s
->sh
;
241 uint8_t nb_list
= sh
->slice_type
== HEVC_SLICE_B
? 2 : 1;
245 ret
= init_slice_rpl(s
);
249 if (!(s
->rps
[ST_CURR_BEF
].nb_refs
+ s
->rps
[ST_CURR_AFT
].nb_refs
+
250 s
->rps
[LT_CURR
].nb_refs
)) {
251 av_log(s
->avctx
, AV_LOG_ERROR
, "Zero refs in the frame RPS.\n");
252 return AVERROR_INVALIDDATA
;
255 for (list_idx
= 0; list_idx
< nb_list
; list_idx
++) {
256 RefPicList rpl_tmp
= { { 0 } };
257 RefPicList
*rpl
= &s
->ref
->refPicList
[list_idx
];
259 /* The order of the elements is
260 * ST_CURR_BEF - ST_CURR_AFT - LT_CURR for the L0 and
261 * ST_CURR_AFT - ST_CURR_BEF - LT_CURR for the L1 */
262 int cand_lists
[3] = { list_idx
? ST_CURR_AFT
: ST_CURR_BEF
,
263 list_idx
? ST_CURR_BEF
: ST_CURR_AFT
,
266 /* concatenate the candidate lists for the current frame */
267 while (rpl_tmp
.nb_refs
< sh
->nb_refs
[list_idx
]) {
268 for (i
= 0; i
< FF_ARRAY_ELEMS(cand_lists
); i
++) {
269 RefPicList
*rps
= &s
->rps
[cand_lists
[i
]];
270 for (j
= 0; j
< rps
->nb_refs
&& rpl_tmp
.nb_refs
< HEVC_MAX_REFS
; j
++) {
271 rpl_tmp
.list
[rpl_tmp
.nb_refs
] = rps
->list
[j
];
272 rpl_tmp
.ref
[rpl_tmp
.nb_refs
] = rps
->ref
[j
];
273 rpl_tmp
.isLongTerm
[rpl_tmp
.nb_refs
] = i
== 2;
279 /* reorder the references if necessary */
280 if (sh
->rpl_modification_flag
[list_idx
]) {
281 for (i
= 0; i
< sh
->nb_refs
[list_idx
]; i
++) {
282 int idx
= sh
->list_entry_lx
[list_idx
][i
];
284 if (idx
>= rpl_tmp
.nb_refs
) {
285 av_log(s
->avctx
, AV_LOG_ERROR
, "Invalid reference index.\n");
286 return AVERROR_INVALIDDATA
;
289 rpl
->list
[i
] = rpl_tmp
.list
[idx
];
290 rpl
->ref
[i
] = rpl_tmp
.ref
[idx
];
291 rpl
->isLongTerm
[i
] = rpl_tmp
.isLongTerm
[idx
];
295 memcpy(rpl
, &rpl_tmp
, sizeof(*rpl
));
296 rpl
->nb_refs
= FFMIN(rpl
->nb_refs
, sh
->nb_refs
[list_idx
]);
299 if (sh
->collocated_list
== list_idx
&&
300 sh
->collocated_ref_idx
< rpl
->nb_refs
)
301 s
->ref
->collocated_ref
= rpl
->ref
[sh
->collocated_ref_idx
];
307 static HEVCFrame
*find_ref_idx(HEVCContext
*s
, int poc
)
310 int LtMask
= (1 << s
->ps
.sps
->log2_max_poc_lsb
) - 1;
312 for (i
= 0; i
< FF_ARRAY_ELEMS(s
->DPB
); i
++) {
313 HEVCFrame
*ref
= &s
->DPB
[i
];
314 if (ref
->frame
->buf
[0] && (ref
->sequence
== s
->seq_decode
)) {
315 if ((ref
->poc
& LtMask
) == poc
)
320 for (i
= 0; i
< FF_ARRAY_ELEMS(s
->DPB
); i
++) {
321 HEVCFrame
*ref
= &s
->DPB
[i
];
322 if (ref
->frame
->buf
[0] && ref
->sequence
== s
->seq_decode
) {
323 if (ref
->poc
== poc
|| (ref
->poc
& LtMask
) == poc
)
328 av_log(s
->avctx
, AV_LOG_ERROR
,
329 "Could not find ref with POC %d\n", poc
);
333 static void mark_ref(HEVCFrame
*frame
, int flag
)
335 frame
->flags
&= ~(HEVC_FRAME_FLAG_LONG_REF
| HEVC_FRAME_FLAG_SHORT_REF
);
336 frame
->flags
|= flag
;
339 static HEVCFrame
*generate_missing_ref(HEVCContext
*s
, int poc
)
344 frame
= alloc_frame(s
);
348 if (!s
->avctx
->hwaccel
) {
349 if (!s
->ps
.sps
->pixel_shift
) {
350 for (i
= 0; frame
->frame
->buf
[i
]; i
++)
351 memset(frame
->frame
->buf
[i
]->data
, 1 << (s
->ps
.sps
->bit_depth
- 1),
352 frame
->frame
->buf
[i
]->size
);
354 for (i
= 0; frame
->frame
->data
[i
]; i
++)
355 for (y
= 0; y
< (s
->ps
.sps
->height
>> s
->ps
.sps
->vshift
[i
]); y
++)
356 for (x
= 0; x
< (s
->ps
.sps
->width
>> s
->ps
.sps
->hshift
[i
]); x
++) {
357 AV_WN16(frame
->frame
->data
[i
] + y
* frame
->frame
->linesize
[i
] + 2 * x
,
358 1 << (s
->ps
.sps
->bit_depth
- 1));
364 frame
->sequence
= s
->seq_decode
;
367 ff_thread_report_progress(&frame
->tf
, INT_MAX
, 0);
372 /* add a reference with the given poc to the list and mark it as used in DPB */
373 static int add_candidate_ref(HEVCContext
*s
, RefPicList
*list
,
374 int poc
, int ref_flag
)
376 HEVCFrame
*ref
= find_ref_idx(s
, poc
);
379 return AVERROR_INVALIDDATA
;
382 ref
= generate_missing_ref(s
, poc
);
384 return AVERROR(ENOMEM
);
387 list
->list
[list
->nb_refs
] = ref
->poc
;
388 list
->ref
[list
->nb_refs
] = ref
;
391 mark_ref(ref
, ref_flag
);
395 int ff_hevc_frame_rps(HEVCContext
*s
)
397 const ShortTermRPS
*short_rps
= s
->sh
.short_term_rps
;
398 const LongTermRPS
*long_rps
= &s
->sh
.long_term_rps
;
399 RefPicList
*rps
= s
->rps
;
403 rps
[0].nb_refs
= rps
[1].nb_refs
= 0;
407 /* clear the reference flags on all frames except the current one */
408 for (i
= 0; i
< FF_ARRAY_ELEMS(s
->DPB
); i
++) {
409 HEVCFrame
*frame
= &s
->DPB
[i
];
417 for (i
= 0; i
< NB_RPS_TYPE
; i
++)
420 /* add the short refs */
421 for (i
= 0; i
< short_rps
->num_delta_pocs
; i
++) {
422 int poc
= s
->poc
+ short_rps
->delta_poc
[i
];
425 if (!short_rps
->used
[i
])
427 else if (i
< short_rps
->num_negative_pics
)
432 ret
= add_candidate_ref(s
, &rps
[list
], poc
, HEVC_FRAME_FLAG_SHORT_REF
);
437 /* add the long refs */
438 for (i
= 0; i
< long_rps
->nb_refs
; i
++) {
439 int poc
= long_rps
->poc
[i
];
440 int list
= long_rps
->used
[i
] ? LT_CURR
: LT_FOLL
;
442 ret
= add_candidate_ref(s
, &rps
[list
], poc
, HEVC_FRAME_FLAG_LONG_REF
);
448 /* release any frames that are now unused */
449 for (i
= 0; i
< FF_ARRAY_ELEMS(s
->DPB
); i
++)
450 ff_hevc_unref_frame(s
, &s
->DPB
[i
], 0);
455 int ff_hevc_compute_poc(HEVCContext
*s
, int poc_lsb
)
457 int max_poc_lsb
= 1 << s
->ps
.sps
->log2_max_poc_lsb
;
458 int prev_poc_lsb
= s
->pocTid0
% max_poc_lsb
;
459 int prev_poc_msb
= s
->pocTid0
- prev_poc_lsb
;
462 if (poc_lsb
< prev_poc_lsb
&& prev_poc_lsb
- poc_lsb
>= max_poc_lsb
/ 2)
463 poc_msb
= prev_poc_msb
+ max_poc_lsb
;
464 else if (poc_lsb
> prev_poc_lsb
&& poc_lsb
- prev_poc_lsb
> max_poc_lsb
/ 2)
465 poc_msb
= prev_poc_msb
- max_poc_lsb
;
467 poc_msb
= prev_poc_msb
;
469 // For BLA picture types, POCmsb is set to 0.
470 if (s
->nal_unit_type
== HEVC_NAL_BLA_W_LP
||
471 s
->nal_unit_type
== HEVC_NAL_BLA_W_RADL
||
472 s
->nal_unit_type
== HEVC_NAL_BLA_N_LP
)
475 return poc_msb
+ poc_lsb
;
478 int ff_hevc_frame_nb_refs(HEVCContext
*s
)
482 const ShortTermRPS
*rps
= s
->sh
.short_term_rps
;
483 LongTermRPS
*long_rps
= &s
->sh
.long_term_rps
;
486 for (i
= 0; i
< rps
->num_negative_pics
; i
++)
487 ret
+= !!rps
->used
[i
];
488 for (; i
< rps
->num_delta_pocs
; i
++)
489 ret
+= !!rps
->used
[i
];
493 for (i
= 0; i
< long_rps
->nb_refs
; i
++)
494 ret
+= !!long_rps
->used
[i
];