1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#include <inttypes.h> 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include "libavutil/log.h" 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include "bsf.h" 24cabdff1aSopenharmony_ci#include "bsf_internal.h" 25cabdff1aSopenharmony_ci#include "cbs.h" 26cabdff1aSopenharmony_ci#include "cbs_bsf.h" 27cabdff1aSopenharmony_ci#include "cbs_h264.h" 28cabdff1aSopenharmony_ci#include "codec_id.h" 29cabdff1aSopenharmony_ci#include "h264.h" 30cabdff1aSopenharmony_ci#include "packet.h" 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_ci#define NEW_GLOBAL_PIC_INIT_QP 26 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_citypedef struct H264RedundantPPSContext { 35cabdff1aSopenharmony_ci CBSBSFContext common; 36cabdff1aSopenharmony_ci} H264RedundantPPSContext; 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_cistatic int h264_redundant_pps_fixup_pps(H264RedundantPPSContext *ctx, 40cabdff1aSopenharmony_ci CodedBitstreamUnit *unit) 41cabdff1aSopenharmony_ci{ 42cabdff1aSopenharmony_ci H264RawPPS *pps; 43cabdff1aSopenharmony_ci int err; 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_ci // The changes we are about to perform affect the parsing process, 46cabdff1aSopenharmony_ci // so we must make sure that the PPS is writable, otherwise the 47cabdff1aSopenharmony_ci // parsing of future slices will be incorrect and even raise errors. 48cabdff1aSopenharmony_ci err = ff_cbs_make_unit_writable(ctx->common.input, unit); 49cabdff1aSopenharmony_ci if (err < 0) 50cabdff1aSopenharmony_ci return err; 51cabdff1aSopenharmony_ci pps = unit->content; 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_ci // Overwrite pic_init_qp with the global value. 54cabdff1aSopenharmony_ci pps->pic_init_qp_minus26 = NEW_GLOBAL_PIC_INIT_QP - 26; 55cabdff1aSopenharmony_ci 56cabdff1aSopenharmony_ci // Some PPSs have this set, so it must be set in all of them. 57cabdff1aSopenharmony_ci // (Slices which do not use such a PPS on input will still have 58cabdff1aSopenharmony_ci // *_weight_l*flag as zero and therefore write equivalently.) 59cabdff1aSopenharmony_ci pps->weighted_pred_flag = 1; 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_ci return 0; 62cabdff1aSopenharmony_ci} 63cabdff1aSopenharmony_ci 64cabdff1aSopenharmony_cistatic int h264_redundant_pps_fixup_slice(H264RedundantPPSContext *ctx, 65cabdff1aSopenharmony_ci H264RawSliceHeader *slice) 66cabdff1aSopenharmony_ci{ 67cabdff1aSopenharmony_ci const CodedBitstreamH264Context *const in = ctx->common.input->priv_data; 68cabdff1aSopenharmony_ci const H264RawPPS *const pps = in->pps[slice->pic_parameter_set_id]; 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci // We modified the PPS's qp value, now offset this by applying 71cabdff1aSopenharmony_ci // the negative offset to the slices. 72cabdff1aSopenharmony_ci slice->slice_qp_delta += pps->pic_init_qp_minus26 73cabdff1aSopenharmony_ci - (NEW_GLOBAL_PIC_INIT_QP - 26); 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci return 0; 76cabdff1aSopenharmony_ci} 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_cistatic int h264_redundant_pps_update_fragment(AVBSFContext *bsf, 79cabdff1aSopenharmony_ci AVPacket *pkt, 80cabdff1aSopenharmony_ci CodedBitstreamFragment *au) 81cabdff1aSopenharmony_ci{ 82cabdff1aSopenharmony_ci H264RedundantPPSContext *ctx = bsf->priv_data; 83cabdff1aSopenharmony_ci int au_has_sps; 84cabdff1aSopenharmony_ci int err, i; 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci au_has_sps = 0; 87cabdff1aSopenharmony_ci for (i = 0; i < au->nb_units; i++) { 88cabdff1aSopenharmony_ci CodedBitstreamUnit *nal = &au->units[i]; 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_ci if (nal->type == H264_NAL_SPS) 91cabdff1aSopenharmony_ci au_has_sps = 1; 92cabdff1aSopenharmony_ci if (nal->type == H264_NAL_PPS) { 93cabdff1aSopenharmony_ci err = h264_redundant_pps_fixup_pps(ctx, nal); 94cabdff1aSopenharmony_ci if (err < 0) 95cabdff1aSopenharmony_ci return err; 96cabdff1aSopenharmony_ci if (!au_has_sps) { 97cabdff1aSopenharmony_ci av_log(bsf, AV_LOG_VERBOSE, "Deleting redundant PPS " 98cabdff1aSopenharmony_ci "at %"PRId64".\n", pkt->pts); 99cabdff1aSopenharmony_ci ff_cbs_delete_unit(au, i); 100cabdff1aSopenharmony_ci i--; 101cabdff1aSopenharmony_ci continue; 102cabdff1aSopenharmony_ci } 103cabdff1aSopenharmony_ci } 104cabdff1aSopenharmony_ci if (nal->type == H264_NAL_SLICE || 105cabdff1aSopenharmony_ci nal->type == H264_NAL_IDR_SLICE) { 106cabdff1aSopenharmony_ci H264RawSlice *slice = nal->content; 107cabdff1aSopenharmony_ci h264_redundant_pps_fixup_slice(ctx, &slice->header); 108cabdff1aSopenharmony_ci } 109cabdff1aSopenharmony_ci } 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ci return 0; 112cabdff1aSopenharmony_ci} 113cabdff1aSopenharmony_ci 114cabdff1aSopenharmony_cistatic const CBSBSFType h264_redundant_pps_type = { 115cabdff1aSopenharmony_ci .codec_id = AV_CODEC_ID_H264, 116cabdff1aSopenharmony_ci .fragment_name = "access unit", 117cabdff1aSopenharmony_ci .unit_name = "NAL unit", 118cabdff1aSopenharmony_ci .update_fragment = &h264_redundant_pps_update_fragment, 119cabdff1aSopenharmony_ci}; 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_cistatic int h264_redundant_pps_init(AVBSFContext *bsf) 122cabdff1aSopenharmony_ci{ 123cabdff1aSopenharmony_ci return ff_cbs_bsf_generic_init(bsf, &h264_redundant_pps_type); 124cabdff1aSopenharmony_ci} 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_cistatic const enum AVCodecID h264_redundant_pps_codec_ids[] = { 127cabdff1aSopenharmony_ci AV_CODEC_ID_H264, AV_CODEC_ID_NONE, 128cabdff1aSopenharmony_ci}; 129cabdff1aSopenharmony_ci 130cabdff1aSopenharmony_ciconst FFBitStreamFilter ff_h264_redundant_pps_bsf = { 131cabdff1aSopenharmony_ci .p.name = "h264_redundant_pps", 132cabdff1aSopenharmony_ci .p.codec_ids = h264_redundant_pps_codec_ids, 133cabdff1aSopenharmony_ci .priv_data_size = sizeof(H264RedundantPPSContext), 134cabdff1aSopenharmony_ci .init = &h264_redundant_pps_init, 135cabdff1aSopenharmony_ci .close = &ff_cbs_bsf_generic_close, 136cabdff1aSopenharmony_ci .filter = &ff_cbs_bsf_generic_filter, 137cabdff1aSopenharmony_ci}; 138