1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "bsf.h"
20 #include "bsf_internal.h"
21 #include "cbs_bsf.h"
22 
cbs_bsf_update_side_data(AVBSFContext *bsf, AVPacket *pkt)23 static int cbs_bsf_update_side_data(AVBSFContext *bsf, AVPacket *pkt)
24 {
25     CBSBSFContext           *ctx = bsf->priv_data;
26     CodedBitstreamFragment *frag = &ctx->fragment;
27     uint8_t *side_data;
28     int err;
29 
30     if (!av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, NULL))
31         return 0;
32 
33     err = ff_cbs_read_packet_side_data(ctx->input, frag, pkt);
34     if (err < 0) {
35         av_log(bsf, AV_LOG_ERROR,
36                "Failed to read extradata from packet side data.\n");
37         return err;
38     }
39 
40     err = ctx->type->update_fragment(bsf, NULL, frag);
41     if (err < 0)
42         return err;
43 
44     err = ff_cbs_write_fragment_data(ctx->output, frag);
45     if (err < 0) {
46         av_log(bsf, AV_LOG_ERROR,
47                "Failed to write extradata into packet side data.\n");
48         return err;
49     }
50 
51     side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
52                                         frag->data_size);
53     if (!side_data)
54         return AVERROR(ENOMEM);
55     memcpy(side_data, frag->data, frag->data_size);
56 
57     ff_cbs_fragment_reset(frag);
58     return 0;
59 }
60 
ff_cbs_bsf_generic_filter(AVBSFContext *bsf, AVPacket *pkt)61 int ff_cbs_bsf_generic_filter(AVBSFContext *bsf, AVPacket *pkt)
62 {
63     CBSBSFContext           *ctx = bsf->priv_data;
64     CodedBitstreamFragment *frag = &ctx->fragment;
65     int err;
66 
67     err = ff_bsf_get_packet_ref(bsf, pkt);
68     if (err < 0)
69         return err;
70 
71     err = cbs_bsf_update_side_data(bsf, pkt);
72     if (err < 0)
73         goto fail;
74 
75     err = ff_cbs_read_packet(ctx->input, frag, pkt);
76     if (err < 0) {
77         av_log(bsf, AV_LOG_ERROR, "Failed to read %s from packet.\n",
78                ctx->type->fragment_name);
79         goto fail;
80     }
81 
82     if (frag->nb_units == 0) {
83         av_log(bsf, AV_LOG_ERROR, "No %s found in packet.\n",
84                ctx->type->unit_name);
85         err = AVERROR_INVALIDDATA;
86         goto fail;
87     }
88 
89     err = ctx->type->update_fragment(bsf, pkt, frag);
90     if (err < 0)
91         goto fail;
92 
93     err = ff_cbs_write_packet(ctx->output, pkt, frag);
94     if (err < 0) {
95         av_log(bsf, AV_LOG_ERROR, "Failed to write %s into packet.\n",
96                ctx->type->fragment_name);
97         goto fail;
98     }
99 
100     err = 0;
101 fail:
102     ff_cbs_fragment_reset(frag);
103 
104     if (err < 0)
105         av_packet_unref(pkt);
106 
107     return err;
108 }
109 
ff_cbs_bsf_generic_init(AVBSFContext *bsf, const CBSBSFType *type)110 int ff_cbs_bsf_generic_init(AVBSFContext *bsf, const CBSBSFType *type)
111 {
112     CBSBSFContext           *ctx = bsf->priv_data;
113     CodedBitstreamFragment *frag = &ctx->fragment;
114     int err;
115 
116     ctx->type = type;
117 
118     err = ff_cbs_init(&ctx->input, type->codec_id, bsf);
119     if (err < 0)
120         return err;
121 
122     err = ff_cbs_init(&ctx->output, type->codec_id, bsf);
123     if (err < 0)
124         return err;
125 
126     if (bsf->par_in->extradata) {
127         err = ff_cbs_read_extradata(ctx->input, frag, bsf->par_in);
128         if (err < 0) {
129             av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n");
130             goto fail;
131         }
132 
133         err = type->update_fragment(bsf, NULL, frag);
134         if (err < 0)
135             goto fail;
136 
137         err = ff_cbs_write_extradata(ctx->output, bsf->par_out, frag);
138         if (err < 0) {
139             av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n");
140             goto fail;
141         }
142     }
143 
144     err = 0;
145 fail:
146     ff_cbs_fragment_reset(frag);
147     return err;
148 }
149 
ff_cbs_bsf_generic_close(AVBSFContext *bsf)150 void ff_cbs_bsf_generic_close(AVBSFContext *bsf)
151 {
152     CBSBSFContext *ctx = bsf->priv_data;
153 
154     ff_cbs_fragment_free(&ctx->fragment);
155     ff_cbs_close(&ctx->input);
156     ff_cbs_close(&ctx->output);
157 }
158