Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2018-2021
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / ffmpeg encode filter
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include <gpac/setup.h>
27 : #include <gpac/bitstream.h>
28 : #include <gpac/avparse.h>
29 :
30 : #ifdef GPAC_HAS_FFMPEG
31 :
32 : #include "ff_common.h"
33 :
34 : #define ENC_BUF_ALLOC_SAFE 10000
35 :
36 : typedef struct _gf_ffenc_ctx
37 : {
38 : //opts
39 : Bool all_intra;
40 : char *c;
41 : Bool ls;
42 : u32 pfmt;
43 : GF_Fraction fintra;
44 : Bool rc;
45 :
46 : //internal data
47 : Bool initialized;
48 :
49 : u32 gop_size;
50 : u32 target_rate;
51 :
52 : AVCodecContext *encoder;
53 : //encode options
54 : AVDictionary *options;
55 :
56 : GF_FilterPid *in_pid, *out_pid;
57 : //media type
58 : u32 type;
59 : u32 timescale;
60 :
61 : u32 nb_frames_out, nb_frames_in;
62 : u64 time_spent;
63 :
64 : Bool low_delay;
65 :
66 : GF_Err (*process)(GF_Filter *filter, struct _gf_ffenc_ctx *ctx);
67 : //gpac one
68 : u32 codecid;
69 : //done flushing encoder (eg sent NULL frames)
70 : u32 flush_done;
71 : //frame used by both video and audio encoder
72 : AVFrame *frame;
73 :
74 : //encoding buffer - we allocate ENC_BUF_ALLOC_SAFE+WxH for the video (some image codecs in ffmpeg require more than WxH for headers), ENC_BUF_ALLOC_SAFE+nb_ch*samplerate for the audio
75 : //this should be enough to hold any lossless compression formats
76 : char *enc_buffer;
77 : u32 enc_buffer_size;
78 :
79 : Bool init_cts_setup;
80 :
81 : //video state
82 : u32 width, height, stride, stride_uv, nb_planes, uv_height;
83 : //ffmpeg one
84 : enum AVPixelFormat pixel_fmt;
85 : u64 cts_first_frame_plus_one;
86 :
87 : //audio state
88 : u32 channels, sample_rate, channel_layout, bytes_per_sample;
89 : //ffmpeg one
90 : u32 sample_fmt;
91 : //we store input audio frame in this buffer until we have enough data for one encoder frame
92 : //we also store the remaining of a consumed frame here, so that input packet is realeased ASAP
93 : char *audio_buffer;
94 : u32 audio_buffer_size;
95 : u32 samples_in_audio_buffer;
96 : //cts of first byte in frame
97 : u64 first_byte_cts;
98 : Bool planar_audio;
99 :
100 : //shift of TS - ffmpeg may give pkt-> PTS < frame->PTS to indicate discard samples
101 : //we convert back to frame PTS but signal discard samples at the PID level
102 : s64 ts_shift;
103 :
104 : GF_List *src_packets;
105 :
106 : GF_BitStream *sdbs;
107 :
108 : Bool reconfig_pending;
109 : Bool infmt_negociate;
110 : Bool remap_ts;
111 : Bool force_reconfig;
112 :
113 : u32 dsi_crc;
114 :
115 : u32 gpac_pixel_fmt;
116 : u32 gpac_audio_fmt;
117 :
118 : Bool fintra_setup;
119 : u64 orig_ts;
120 : u32 nb_forced;
121 :
122 : AVCodec *force_codec;
123 :
124 : //we don't forward media delay, we directly offset CTS/DTS
125 : s64 in_tk_delay;
126 :
127 : Bool discontunity;
128 : GF_FilterPacket *disc_pck_ref;
129 : } GF_FFEncodeCtx;
130 :
131 : static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove, Bool is_force_reconf);
132 :
133 : static const GF_FilterCapability FFEncodeCapsVideo[] =
134 : {
135 : CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
136 : CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
137 : CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
138 : CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW),
139 : CAP_BOOL(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_TILE_BASE, GF_TRUE)
140 : };
141 :
142 : static const GF_FilterCapability FFEncodeCapsAudio[] =
143 : {
144 : CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
145 : CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
146 : CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
147 : CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW)
148 : };
149 :
150 14 : static void ffenc_override_caps(GF_Filter *filter, u32 media_type)
151 : {
152 14 : if (media_type==AVMEDIA_TYPE_AUDIO) {
153 4 : gf_filter_override_caps(filter, FFEncodeCapsAudio, GF_ARRAY_LENGTH(FFEncodeCapsAudio) );
154 : } else {
155 10 : gf_filter_override_caps(filter, FFEncodeCapsVideo, GF_ARRAY_LENGTH(FFEncodeCapsVideo) );
156 : }
157 14 : }
158 :
159 32 : static GF_Err ffenc_initialize(GF_Filter *filter)
160 : {
161 : u32 codec_id;
162 32 : GF_FFEncodeCtx *ctx = (GF_FFEncodeCtx *) gf_filter_get_udta(filter);
163 32 : ctx->initialized = GF_TRUE;
164 32 : ctx->src_packets = gf_list_new();
165 32 : ctx->sdbs = gf_bs_new((u8*)ctx, 1, GF_BITSTREAM_READ);
166 :
167 32 : ffmpeg_setup_logs(GF_LOG_CODEC);
168 :
169 :
170 32 : if (!ctx->c) return GF_OK;
171 :
172 : //first look by name, to handle cases such as "aac" vs "vo_aacenc"
173 14 : ctx->force_codec = avcodec_find_encoder_by_name(ctx->c);
174 14 : if (ctx->force_codec) {
175 4 : ffenc_override_caps(filter, ctx->force_codec->type);
176 4 : return GF_OK;
177 : }
178 : //then look by codec ID
179 10 : codec_id = gf_codecid_parse(ctx->c);
180 10 : if (codec_id!=GF_CODECID_NONE) {
181 10 : ctx->force_codec = avcodec_find_encoder(ffmpeg_codecid_from_gpac(codec_id, NULL) );
182 : }
183 10 : if (!ctx->force_codec) return GF_NOT_SUPPORTED;
184 10 : ffenc_override_caps(filter, ctx->force_codec->type);
185 10 : ctx->force_codec = NULL;
186 10 : return GF_OK;
187 : }
188 :
189 32 : static void ffenc_finalize(GF_Filter *filter)
190 : {
191 32 : GF_FFEncodeCtx *ctx = (GF_FFEncodeCtx *) gf_filter_get_udta(filter);
192 32 : if (ctx->options) av_dict_free(&ctx->options);
193 32 : if (ctx->frame) av_frame_free(&ctx->frame);
194 32 : if (ctx->enc_buffer) gf_free(ctx->enc_buffer);
195 32 : if (ctx->audio_buffer) gf_free(ctx->audio_buffer);
196 :
197 35 : while (gf_list_count(ctx->src_packets)) {
198 3 : GF_FilterPacket *pck = gf_list_pop_back(ctx->src_packets);
199 3 : gf_filter_pck_unref(pck);
200 : }
201 32 : gf_list_del(ctx->src_packets);
202 :
203 32 : if (ctx->encoder) {
204 32 : avcodec_free_context(&ctx->encoder);
205 : }
206 32 : if (ctx->sdbs) gf_bs_del(ctx->sdbs);
207 32 : return;
208 : }
209 :
210 92 : static void ffenc_copy_pid_props(GF_FFEncodeCtx *ctx)
211 : {
212 : //copy properties at init or reconfig
213 92 : gf_filter_pid_copy_properties(ctx->out_pid, ctx->in_pid);
214 92 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_DECODER_CONFIG, NULL);
215 92 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_CODECID, &PROP_UINT(ctx->codecid) );
216 92 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_ISOM_STSD_TEMPLATE, NULL);
217 :
218 92 : switch (ctx->codecid) {
219 32 : case GF_CODECID_AVC:
220 : case GF_CODECID_HEVC:
221 : case GF_CODECID_MPEG4_PART2:
222 32 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_UNFRAMED, &PROP_BOOL(GF_TRUE) );
223 32 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_UNFRAMED_FULL_AU, &PROP_BOOL(GF_TRUE) );
224 32 : break;
225 60 : default:
226 60 : if (ctx->encoder && ctx->encoder->extradata_size && ctx->encoder->extradata) {
227 4 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA(ctx->encoder->extradata, ctx->encoder->extradata_size) );
228 : }
229 : break;
230 : }
231 : //if target rate is not known yet (encoder default and we setup an adaptation chain for the PID), signal a default 100k
232 : //this prevents a warning in the dasher complaining that no rate is set, unaware that we will reconfigure the PID before sending data
233 92 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_BITRATE, &PROP_UINT(ctx->target_rate ? ctx->target_rate : 100000));
234 :
235 92 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_TARGET_RATE, NULL);
236 :
237 92 : if (ctx->ts_shift) {
238 0 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_DELAY, &PROP_LONGSINT( - ctx->ts_shift) );
239 : } else {
240 92 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_DELAY, NULL);
241 : }
242 92 : if (ctx->width && ctx->height) {
243 44 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_HAS_SYNC, ctx->all_intra ? NULL : &PROP_BOOL(GF_TRUE) );
244 : }
245 92 : }
246 :
247 10427 : static u64 ffenc_get_cts(GF_FFEncodeCtx *ctx, GF_FilterPacket *pck)
248 : {
249 10427 : u64 ts = gf_filter_pck_get_cts(pck);
250 10427 : if ((ctx->in_tk_delay<0) && (ts < (u64) -ctx->in_tk_delay)) {
251 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FFEnc] Negative input TS \n"));
252 : return 0;
253 : }
254 10427 : return ts + ctx->in_tk_delay;
255 : }
256 :
257 : //TODO add more feedback
258 2806 : static void ffenc_log_video(GF_Filter *filter, struct _gf_ffenc_ctx *ctx, AVPacket *pkt, Bool do_reporting)
259 : {
260 : Double fps=0;
261 : s32 q=-1;
262 : u8 pictype=0;
263 : #if LIBAVCODEC_VERSION_MAJOR >= 58
264 : u64 errors[10];
265 : u32 i;
266 : u8 nb_errors = 0;
267 : #endif
268 : const char *ptype = "U";
269 :
270 2806 : if (!ctx->ls && !do_reporting) return;
271 :
272 :
273 : #if LIBAVCODEC_VERSION_MAJOR >= 58
274 : u32 sq_size;
275 : u8 *side_q = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, &sq_size);
276 : if (side_q) {
277 : gf_bs_reassign_buffer(ctx->sdbs, side_q, sq_size);
278 : q = gf_bs_read_u32_le(ctx->sdbs);
279 : pictype = gf_bs_read_u8(ctx->sdbs);
280 : nb_errors = gf_bs_read_u8(ctx->sdbs);
281 : /*res*/gf_bs_read_u16(ctx->sdbs);
282 : if (nb_errors>10) nb_errors = 10;
283 : for (i=0; i<nb_errors; i++) {
284 : errors[i] = gf_bs_read_u64_le(ctx->sdbs);
285 : }
286 : }
287 : #endif
288 262 : if (ctx->time_spent) {
289 262 : fps = ctx->nb_frames_out;
290 262 : fps *= 1000000;
291 262 : fps /= ctx->time_spent;
292 : }
293 : switch (pictype) {
294 : case AV_PICTURE_TYPE_I: ptype = "I"; break;
295 : case AV_PICTURE_TYPE_P: ptype = "P"; break;
296 : case AV_PICTURE_TYPE_S: ptype = "S"; break;
297 : case AV_PICTURE_TYPE_SP: ptype = "SP"; break;
298 : case AV_PICTURE_TYPE_B: ptype = "B"; break;
299 : case AV_PICTURE_TYPE_BI: ptype = "B"; break;
300 : }
301 :
302 262 : if (ctx->ls) {
303 262 : fprintf(stderr, "[FFEnc] FPS %.02f F %d DTS "LLD" CTS "LLD" Q %02.02f PT %s (F_in %d)", fps, ctx->nb_frames_out, pkt->dts+ctx->ts_shift, pkt->pts+ctx->ts_shift, ((Double)q) / FF_QP2LAMBDA, ptype, ctx->nb_frames_in);
304 : #if LIBAVCODEC_VERSION_MAJOR >= 58
305 : if (nb_errors) {
306 : fprintf(stderr, "PSNR");
307 : for (i=0; i<nb_errors; i++) {
308 : Double psnr = (Double) errors[i];
309 : psnr /= ctx->width * ctx->height * 255.0 * 255.0;
310 : fprintf(stderr, " %02.02f", psnr);
311 : }
312 : }
313 : #endif
314 262 : fprintf(stderr, "\r");
315 : }
316 :
317 262 : if (do_reporting) {
318 : char szStatus[1024];
319 0 : sprintf(szStatus, "[FFEnc] FPS %.02f F %d DTS "LLD" CTS "LLD" Q %02.02f PT %s (F_in %d)", fps, ctx->nb_frames_out, pkt->dts+ctx->ts_shift, pkt->pts+ctx->ts_shift, ((Double)q) / FF_QP2LAMBDA, ptype, ctx->nb_frames_in);
320 0 : gf_filter_update_status(filter, -1, szStatus);
321 : }
322 : }
323 :
324 3141 : static GF_Err ffenc_process_video(GF_Filter *filter, struct _gf_ffenc_ctx *ctx)
325 : {
326 : AVPacket pkt;
327 : s32 gotpck;
328 : const char *data = NULL;
329 3141 : u32 size=0, i, count, offset, to_copy;
330 : s32 res;
331 : u64 now;
332 : u8 *output;
333 : u32 force_intra = 0;
334 : Bool insert_jp2c = GF_FALSE;
335 : GF_FilterPacket *dst_pck, *src_pck;
336 : GF_FilterPacket *pck;
337 : const GF_PropertyValue *p;
338 :
339 3141 : if (!ctx->in_pid) return GF_EOS;
340 :
341 3141 : pck = gf_filter_pid_get_packet(ctx->in_pid);
342 :
343 3141 : if (!ctx->encoder) {
344 4 : if (ctx->infmt_negociate) return GF_OK;
345 :
346 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFEnc] encoder reconfiguration failed, aborting stream\n"));
347 0 : gf_filter_pid_set_eos(ctx->out_pid);
348 0 : return GF_EOS;
349 : }
350 :
351 3137 : if (!pck) {
352 331 : if (! gf_filter_pid_is_eos(ctx->in_pid)) return GF_OK;
353 331 : if (ctx->flush_done) return GF_OK;
354 : }
355 :
356 3129 : if (ctx->reconfig_pending) pck = NULL;
357 :
358 3129 : if (pck) data = gf_filter_pck_get_data(pck, &size);
359 :
360 3129 : av_init_packet(&pkt);
361 3129 : pkt.data = (uint8_t*)ctx->enc_buffer;
362 3129 : pkt.size = ctx->enc_buffer_size;
363 :
364 3129 : ctx->frame->pict_type = 0;
365 3129 : ctx->frame->width = ctx->width;
366 3129 : ctx->frame->height = ctx->height;
367 3129 : ctx->frame->format = ctx->pixel_fmt;
368 :
369 3129 : ctx->frame->pict_type = AV_PICTURE_TYPE_NONE;
370 :
371 : //force picture type
372 3129 : if (ctx->all_intra)
373 0 : ctx->frame->pict_type = AV_PICTURE_TYPE_I;
374 :
375 : //if PCK_FILENUM is set on input, this is a file boundary, force IDR sync
376 3129 : if (pck && gf_filter_pck_get_property(pck, GF_PROP_PCK_FILENUM)) {
377 : force_intra = 2;
378 : }
379 : //if CUE_START is set on input, this is a segment boundary, force IDR sync
380 3129 : p = pck ? gf_filter_pck_get_property(pck, GF_PROP_PCK_CUE_START) : NULL;
381 2806 : if (p && p->value.boolean) {
382 : force_intra = 2;
383 : }
384 :
385 : //check if we need to force a closed gop
386 3129 : if (pck && (ctx->fintra.den && (ctx->fintra.num>0)) && !ctx->force_reconfig) {
387 1538 : u64 cts = ffenc_get_cts(ctx, pck);
388 1538 : if (!ctx->fintra_setup) {
389 8 : ctx->fintra_setup = GF_TRUE;
390 8 : ctx->orig_ts = cts;
391 : force_intra = 1;
392 8 : ctx->nb_forced=1;
393 1530 : } else if (cts < ctx->orig_ts) {
394 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FFEnc] timestamps not increasing monotonuously, reseting forced intra state !\n"));
395 0 : ctx->orig_ts = cts;
396 : force_intra = 1;
397 0 : ctx->nb_forced=1;
398 : } else {
399 1530 : u64 ts_diff = cts - ctx->orig_ts;
400 1530 : if (ts_diff * ctx->fintra.den >= ctx->nb_forced * ctx->fintra.num * ctx->timescale) {
401 : force_intra = 1;
402 54 : ctx->nb_forced++;
403 54 : GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[FFEnc] Forcing IDR at frame %d (CTS %d / %d)\n", ctx->nb_frames_in, cts, ctx->timescale));
404 : }
405 : }
406 : }
407 :
408 3067 : if (force_intra) {
409 : //file switch we force a full reset to force injecting xPS in the stream
410 : //we could also inject them manually but we don't have them !!
411 62 : if ((ctx->rc && ctx->nb_frames_in) || (force_intra==2)) {
412 0 : if (!ctx->force_reconfig) {
413 0 : ctx->reconfig_pending = GF_TRUE;
414 0 : ctx->force_reconfig = GF_TRUE;
415 0 : pck = NULL;
416 : } else {
417 0 : ctx->force_reconfig = GF_FALSE;
418 : }
419 : }
420 62 : ctx->frame->pict_type = AV_PICTURE_TYPE_I;
421 : }
422 :
423 :
424 3129 : now = gf_sys_clock_high_res();
425 3129 : gotpck = 0;
426 3129 : if (pck) {
427 : u32 ilaced;
428 2806 : if (data) {
429 2621 : ctx->frame->data[0] = (u8 *) data;
430 2621 : ctx->frame->linesize[0] = ctx->stride;
431 2621 : if (ctx->nb_planes>1) {
432 2619 : ctx->frame->data[1] = (u8 *) data + ctx->stride * ctx->height;
433 2619 : ctx->frame->linesize[1] = ctx->stride_uv ? ctx->stride_uv : ctx->stride/2;
434 2619 : if (ctx->nb_planes>2) {
435 2619 : ctx->frame->data[2] = (u8 *) ctx->frame->data[1] + ctx->stride_uv * ctx->height/2;
436 2619 : ctx->frame->linesize[2] = ctx->frame->linesize[1];
437 : } else {
438 0 : ctx->frame->linesize[2] = 0;
439 : }
440 : } else {
441 2 : ctx->frame->linesize[1] = 0;
442 : }
443 : } else {
444 : GF_Err e=GF_NOT_SUPPORTED;
445 185 : GF_FilterFrameInterface *frame_ifce = gf_filter_pck_get_frame_interface(pck);
446 185 : if (frame_ifce && frame_ifce->get_plane) {
447 185 : e = frame_ifce->get_plane(frame_ifce, 0, (const u8 **) &ctx->frame->data[0], &ctx->frame->linesize[0]);
448 185 : if (!e && (ctx->nb_planes>1)) {
449 185 : e = frame_ifce->get_plane(frame_ifce, 1, (const u8 **) &ctx->frame->data[1], &ctx->frame->linesize[1]);
450 185 : if (!e && (ctx->nb_planes>2)) {
451 185 : e = frame_ifce->get_plane(frame_ifce, 1, (const u8 **) &ctx->frame->data[2], &ctx->frame->linesize[2]);
452 : }
453 : }
454 : }
455 185 : if (e) {
456 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFEnc] Failed to fetch %sframe data: %s\n", frame_ifce ? "hardware " : "", gf_error_to_string(e) ));
457 0 : gf_filter_pid_drop_packet(ctx->in_pid);
458 0 : return e;
459 : }
460 : }
461 :
462 2806 : ilaced = gf_filter_pck_get_interlaced(pck);
463 2806 : if (!ilaced) {
464 2806 : ctx->frame->interlaced_frame = 0;
465 : } else {
466 0 : ctx->frame->interlaced_frame = 1;
467 0 : ctx->frame->top_field_first = (ilaced==2) ? 1 : 0;
468 : }
469 2806 : ctx->frame->pts = ffenc_get_cts(ctx, pck);
470 2806 : ctx->frame->pkt_duration = gf_filter_pck_get_duration(pck);
471 :
472 : #define SCALE_TS(_ts) if (_ts != GF_FILTER_NO_TS) { _ts *= ctx->encoder->time_base.den; _ts /= ctx->timescale; }
473 : #define UNSCALE_TS(_ts) if (_ts != AV_NOPTS_VALUE) { _ts *= ctx->timescale; _ts /= ctx->encoder->time_base.den; }
474 : #define UNSCALE_DUR(_ts) { _ts *= ctx->timescale; _ts /= ctx->encoder->time_base.den; }
475 :
476 : //store first frame CTS before rescaling, we use it after rescaling the output packet timing to compute CTS-DTS
477 2806 : if (!ctx->cts_first_frame_plus_one) {
478 24 : ctx->cts_first_frame_plus_one = 1 + ctx->frame->pts;
479 : }
480 :
481 2806 : if (ctx->remap_ts) {
482 2803 : SCALE_TS(ctx->frame->pts);
483 :
484 2803 : SCALE_TS(ctx->frame->pkt_duration);
485 : }
486 :
487 2806 : ctx->frame->pkt_dts = ctx->frame->pkt_pts = ctx->frame->pts;
488 2806 : res = avcodec_encode_video2(ctx->encoder, &pkt, ctx->frame, &gotpck);
489 2806 : ctx->nb_frames_in++;
490 :
491 : //keep ref to ource properties
492 2806 : gf_filter_pck_ref_props(&pck);
493 2806 : gf_list_add(ctx->src_packets, pck);
494 2806 : if (ctx->discontunity) {
495 0 : ctx->discontunity = GF_FALSE;
496 0 : ctx->disc_pck_ref = pck;
497 : }
498 :
499 2806 : gf_filter_pid_drop_packet(ctx->in_pid);
500 :
501 2806 : if (ctx->remap_ts) {
502 2803 : UNSCALE_TS(ctx->frame->pts);
503 2803 : UNSCALE_TS(ctx->frame->pkt_duration);
504 :
505 2803 : UNSCALE_TS(pkt.dts);
506 2803 : UNSCALE_TS(pkt.pts);
507 2803 : UNSCALE_DUR(pkt.duration);
508 : }
509 : } else {
510 323 : res = avcodec_encode_video2(ctx->encoder, &pkt, NULL, &gotpck);
511 323 : if (!gotpck) {
512 : //done flushing encoder while reconfiguring
513 24 : if (ctx->reconfig_pending) {
514 : GF_Err e;
515 0 : Bool bck_init_cts = ctx->init_cts_setup;
516 0 : ctx->reconfig_pending = GF_FALSE;
517 0 : ctx->force_reconfig = GF_FALSE;
518 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FFEnc] codec flush done, triggering reconfiguration\n"));
519 0 : avcodec_close(ctx->encoder);
520 0 : ctx->encoder = NULL;
521 0 : e = ffenc_configure_pid_ex(filter, ctx->in_pid, GF_FALSE, GF_TRUE);
522 0 : ctx->init_cts_setup = bck_init_cts;
523 0 : return e;
524 : }
525 24 : ctx->flush_done = 1;
526 24 : gf_filter_pid_set_eos(ctx->out_pid);
527 24 : return GF_EOS;
528 : }
529 299 : if (ctx->remap_ts) {
530 299 : UNSCALE_TS(pkt.dts);
531 299 : UNSCALE_TS(pkt.pts);
532 299 : UNSCALE_DUR(pkt.duration);
533 : }
534 : }
535 3105 : now = gf_sys_clock_high_res() - now;
536 3105 : ctx->time_spent += now;
537 :
538 3105 : if (res<0) {
539 0 : av_packet_free_side_data(&pkt);
540 0 : ctx->nb_frames_out++;
541 0 : return GF_SERVICE_ERROR;
542 : }
543 :
544 3105 : if (!gotpck) {
545 299 : av_packet_free_side_data(&pkt);
546 299 : return GF_OK;
547 : }
548 :
549 2806 : ctx->nb_frames_out++;
550 2806 : if (ctx->init_cts_setup) {
551 24 : ctx->init_cts_setup = GF_FALSE;
552 24 : if (ctx->frame->pts != pkt.pts) {
553 : //check shift in PTS - most of the time this is 0 (ffmpeg does not restamp video pts)
554 14 : ctx->ts_shift = (s64) ctx->cts_first_frame_plus_one - 1 - (s64) pkt.pts;
555 :
556 : //check shift in DTS
557 14 : ctx->ts_shift += (s64) ctx->cts_first_frame_plus_one - 1 - (s64) pkt.dts;
558 : }
559 :
560 : //if ts_shift>0, this means we have a skip
561 24 : if (ctx->ts_shift) {
562 12 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_DELAY, &PROP_LONGSINT( -ctx->ts_shift ) );
563 : } else {
564 12 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_DELAY, NULL);
565 : }
566 : }
567 :
568 : src_pck = NULL;
569 2806 : count = gf_list_count(ctx->src_packets);
570 3888 : for (i=0; i<count; i++) {
571 3888 : src_pck = gf_list_get(ctx->src_packets, i);
572 3888 : if (ffenc_get_cts(ctx, src_pck) == pkt.pts) break;
573 : src_pck = NULL;
574 : }
575 :
576 : offset = 0;
577 2806 : to_copy = size = pkt.size;
578 :
579 2806 : if (ctx->codecid == GF_CODECID_J2K) {
580 262 : u32 b4cc = GF_4CC(pkt.data[4], pkt.data[5], pkt.data[6], pkt.data[7]);
581 262 : if (b4cc == GF_4CC('j','P',' ',' ')) {
582 : u32 jp2h_offset = 0;
583 : offset = 12;
584 17292 : while (offset+8 < (u32) pkt.size) {
585 17292 : b4cc = GF_4CC(pkt.data[offset+4], pkt.data[offset+5], pkt.data[offset+6], pkt.data[offset+7]);
586 17292 : if (b4cc == GF_4CC('j','p','2','c')) {
587 : break;
588 : }
589 17030 : if (b4cc == GF_4CC('j','p','2','h')) {
590 : jp2h_offset = offset;
591 : }
592 17030 : offset++;
593 : }
594 262 : if (jp2h_offset) {
595 262 : u32 len = pkt.data[jp2h_offset];
596 262 : len <<= 8;
597 262 : len |= pkt.data[jp2h_offset+1];
598 262 : len <<= 8;
599 262 : len |= pkt.data[jp2h_offset+2];
600 262 : len <<= 8;
601 262 : len |= pkt.data[jp2h_offset+3];
602 :
603 262 : u32 dsi_crc = gf_crc_32(pkt.data + jp2h_offset + 8, len-8);
604 262 : if (dsi_crc != ctx->dsi_crc) {
605 2 : ctx->dsi_crc = dsi_crc;
606 2 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA(pkt.data + jp2h_offset + 8, len-8) );
607 : }
608 : }
609 262 : size -= offset;
610 262 : to_copy -= offset;
611 : } else {
612 0 : size += 8;
613 :
614 0 : if (!ctx->dsi_crc) {
615 : u8 *dsi;
616 : u32 dsi_len;
617 0 : GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
618 0 : gf_bs_write_u32(bs, 14+8);
619 0 : gf_bs_write_u32(bs, GF_4CC('i','h','d','r'));
620 0 : gf_bs_write_u32(bs, ctx->height);
621 0 : gf_bs_write_u32(bs, ctx->width);
622 0 : gf_bs_write_u16(bs, ctx->nb_planes);
623 0 : gf_bs_write_u8(bs, gf_pixel_get_bytes_per_pixel(ctx->gpac_pixel_fmt));
624 0 : gf_bs_write_u8(bs, 7); //COMP
625 0 : gf_bs_write_u8(bs, 0);
626 0 : gf_bs_write_u8(bs, 0);
627 0 : gf_bs_get_content(bs, &dsi, &dsi_len);
628 0 : gf_bs_del(bs);
629 0 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_len) );
630 0 : ctx->dsi_crc = 1;
631 : }
632 : }
633 : }
634 :
635 2806 : dst_pck = gf_filter_pck_new_alloc(ctx->out_pid, size, &output);
636 2806 : if (!dst_pck) return GF_OUT_OF_MEM;
637 :
638 : if (insert_jp2c) {
639 : u32 bsize = pkt.size + 8;
640 : output[0] = (bsize >> 24) & 0xFF;
641 : output[1] = (bsize >> 16) & 0xFF;
642 : output[2] = (bsize >> 8) & 0xFF;
643 : output[3] = (bsize) & 0xFF;
644 : output[4] = 'j';
645 : output[5] = 'p';
646 : output[6] = '2';
647 : output[7] = 'c';
648 : output += 8;
649 : }
650 2806 : memcpy(output, pkt.data + offset, to_copy);
651 :
652 2806 : if (src_pck) {
653 2806 : if (ctx->disc_pck_ref == src_pck) {
654 0 : ctx->disc_pck_ref = NULL;
655 0 : ffenc_copy_pid_props(ctx);
656 : }
657 :
658 2806 : gf_filter_pck_merge_properties(src_pck, dst_pck);
659 2806 : gf_list_del_item(ctx->src_packets, src_pck);
660 2806 : gf_filter_pck_unref(src_pck);
661 : } else {
662 0 : if (pkt.duration) {
663 0 : gf_filter_pck_set_duration(dst_pck, (u32) pkt.duration);
664 : } else {
665 0 : gf_filter_pck_set_duration(dst_pck, (u32) ctx->frame->pkt_duration);
666 : }
667 : }
668 :
669 2806 : ffenc_log_video(filter, ctx, &pkt, gf_filter_reporting_enabled(filter));
670 :
671 2806 : gf_filter_pck_set_cts(dst_pck, pkt.pts + ctx->ts_shift);
672 2806 : gf_filter_pck_set_dts(dst_pck, pkt.dts + ctx->ts_shift);
673 :
674 : //this is not 100% correct since we don't have any clue if this is SAP1/2/3/4 ...
675 : //since we send the output to our reframers we should be fine
676 2806 : if (pkt.flags & AV_PKT_FLAG_KEY) {
677 404 : gf_filter_pck_set_sap(dst_pck, GF_FILTER_SAP_1);
678 404 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FFEnc] frame %d is SAP\n", ctx->nb_frames_out));
679 : }
680 : else
681 2402 : gf_filter_pck_set_sap(dst_pck, 0);
682 :
683 : #if LIBAVCODEC_VERSION_MAJOR >= 58
684 : if (pkt.flags & AV_PKT_FLAG_DISPOSABLE) {
685 : gf_filter_pck_set_dependency_flags(dst_pck, 0x8);
686 : }
687 : #endif
688 2806 : gf_filter_pck_send(dst_pck);
689 :
690 2806 : av_packet_free_side_data(&pkt);
691 :
692 : //we're in final flush, request a process task until all frames flushe
693 : //we could recursiveley call ourselves, same result
694 2806 : if (!pck) {
695 299 : gf_filter_post_process_task(filter);
696 : }
697 : return GF_OK;
698 : }
699 :
700 :
701 :
702 2878 : static void ffenc_audio_append_samples(struct _gf_ffenc_ctx *ctx, const u8 *data, u32 size, u32 sample_offset, u32 nb_samples)
703 : {
704 : u8 *dst;
705 : u32 f_idx, s_idx;
706 : u32 i, bytes_per_chan, src_frame_size;
707 :
708 2878 : if (!ctx->audio_buffer || !nb_samples)
709 : return;
710 :
711 2878 : if (!ctx->planar_audio) {
712 618 : u32 offset_src = sample_offset * ctx->bytes_per_sample;
713 618 : u32 offset_dst = ctx->samples_in_audio_buffer * ctx->bytes_per_sample;
714 618 : u32 len = nb_samples * ctx->bytes_per_sample;
715 618 : if (data)
716 617 : memcpy(ctx->audio_buffer + offset_dst, data + offset_src, sizeof(u8)*len);
717 : else
718 1 : memset(ctx->audio_buffer + offset_dst, 0, sizeof(u8)*len);
719 618 : ctx->samples_in_audio_buffer += nb_samples;
720 618 : return;
721 : }
722 :
723 2260 : bytes_per_chan = ctx->bytes_per_sample / ctx->channels;
724 2260 : src_frame_size = size / ctx->bytes_per_sample;
725 : assert(ctx->samples_in_audio_buffer + nb_samples <= (u32) ctx->audio_buffer_size);
726 : assert(!data || (sample_offset + nb_samples <= src_frame_size));
727 : assert(ctx->encoder->frame_size);
728 :
729 2260 : f_idx = ctx->samples_in_audio_buffer / ctx->encoder->frame_size;
730 2260 : s_idx = ctx->samples_in_audio_buffer % ctx->encoder->frame_size;
731 : if (s_idx) {
732 : assert(s_idx + nb_samples <= (u32) ctx->encoder->frame_size);
733 : }
734 2260 : dst = ctx->audio_buffer + (f_idx * ctx->channels * ctx->encoder->frame_size + s_idx) * bytes_per_chan;
735 6780 : while (nb_samples) {
736 : const u8 *src = NULL;
737 : u32 nb_samples_to_copy = nb_samples;
738 2260 : if (nb_samples_to_copy > (u32) ctx->encoder->frame_size)
739 : nb_samples_to_copy = ctx->encoder->frame_size;
740 :
741 2260 : if (data) {
742 : assert(sample_offset<src_frame_size);
743 2256 : src = data + sample_offset * bytes_per_chan;
744 : }
745 :
746 4520 : for (i=0; i<ctx->channels; i++) {
747 4520 : if (src) {
748 4512 : memcpy(dst, src, sizeof(u8) * nb_samples_to_copy * bytes_per_chan);
749 4512 : src += src_frame_size * bytes_per_chan;
750 : } else {
751 8 : memset(dst, 0, sizeof(u8) * nb_samples_to_copy * bytes_per_chan);
752 : }
753 4520 : dst += ctx->encoder->frame_size * bytes_per_chan;
754 : }
755 2260 : ctx->samples_in_audio_buffer += nb_samples_to_copy;
756 2260 : nb_samples -= nb_samples_to_copy;
757 2260 : sample_offset += nb_samples_to_copy;
758 : }
759 : }
760 :
761 1942 : static GF_Err ffenc_process_audio(GF_Filter *filter, struct _gf_ffenc_ctx *ctx)
762 : {
763 : AVPacket pkt;
764 : s32 gotpck;
765 : const char *data = NULL;
766 1942 : u32 size=0, nb_copy=0, i, count;
767 : Bool from_internal_buffer_only = GF_FALSE;
768 : s32 res;
769 : u32 nb_samples=0;
770 : u64 ts_diff;
771 : u8 *output;
772 : GF_FilterPacket *dst_pck, *src_pck;
773 : GF_FilterPacket *pck;
774 :
775 1942 : if (!ctx->in_pid) return GF_EOS;
776 :
777 1942 : pck = gf_filter_pid_get_packet(ctx->in_pid);
778 :
779 1942 : if (!ctx->encoder) {
780 0 : if (ctx->infmt_negociate) return GF_OK;
781 :
782 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFEnc] encoder reconfiguration failed, aborting stream\n"));
783 0 : gf_filter_pid_set_eos(ctx->out_pid);
784 0 : return GF_EOS;
785 : }
786 :
787 1942 : if (!pck) {
788 21 : if (! gf_filter_pid_is_eos(ctx->in_pid)) return GF_OK;
789 21 : if (ctx->flush_done) return GF_EOS;
790 : }
791 :
792 1942 : if (ctx->reconfig_pending) pck = NULL;
793 :
794 1942 : if (ctx->encoder->frame_size && (ctx->encoder->frame_size <= (s32) ctx->samples_in_audio_buffer)) {
795 0 : avcodec_fill_audio_frame(ctx->frame, ctx->channels, ctx->sample_fmt, ctx->audio_buffer, ctx->bytes_per_sample * ctx->encoder->frame_size, 0);
796 :
797 0 : from_internal_buffer_only = GF_TRUE;
798 :
799 1942 : } else if (pck) {
800 1919 : data = gf_filter_pck_get_data(pck, &size);
801 1919 : if (!data) {
802 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FFEnc] Packet without associated data\n"));
803 0 : gf_filter_pid_drop_packet(ctx->in_pid);
804 0 : return GF_OK;
805 : }
806 :
807 1919 : if (!ctx->samples_in_audio_buffer) {
808 166 : ctx->first_byte_cts = ffenc_get_cts(ctx, pck);
809 : }
810 :
811 1919 : src_pck = pck;
812 1919 : gf_filter_pck_ref_props(&src_pck);
813 1919 : gf_list_add(ctx->src_packets, src_pck);
814 1919 : if (ctx->discontunity) {
815 0 : ctx->disc_pck_ref = src_pck;
816 0 : ctx->discontunity = GF_FALSE;
817 : }
818 :
819 1919 : nb_samples = size / ctx->bytes_per_sample;
820 1919 : if (ctx->encoder->frame_size && (nb_samples + ctx->samples_in_audio_buffer < (u32) ctx->encoder->frame_size)) {
821 804 : ffenc_audio_append_samples(ctx, data, size, 0, nb_samples);
822 804 : gf_filter_pid_drop_packet(ctx->in_pid);
823 804 : return GF_OK;
824 : }
825 :
826 1115 : if (ctx->encoder->frame_size) {
827 1115 : nb_copy = ctx->encoder->frame_size - ctx->samples_in_audio_buffer;
828 1115 : ffenc_audio_append_samples(ctx, data, size, 0, nb_copy);
829 :
830 1115 : ctx->frame->nb_samples = ctx->encoder->frame_size;
831 1115 : res = avcodec_fill_audio_frame(ctx->frame, ctx->channels, ctx->sample_fmt, ctx->audio_buffer, ctx->encoder->frame_size*ctx->bytes_per_sample, 0);
832 :
833 : } else {
834 0 : ctx->frame->nb_samples = size / ctx->bytes_per_sample;
835 0 : res = avcodec_fill_audio_frame(ctx->frame, ctx->channels, ctx->sample_fmt, data, size, 0);
836 : data = NULL;
837 0 : size = 0;
838 : }
839 1115 : if (res<0) {
840 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFEnc] Error filling raw audio frame: %s\n", av_err2str(res) ));
841 : //discard
842 0 : ctx->samples_in_audio_buffer = 0;
843 0 : if (data && (nb_samples > nb_copy)) {
844 0 : ffenc_audio_append_samples(ctx, data, size, nb_copy, nb_samples - nb_copy);
845 0 : ts_diff = nb_copy;
846 0 : ts_diff *= ctx->timescale;
847 0 : ts_diff /= ctx->sample_rate;
848 0 : ctx->first_byte_cts = ffenc_get_cts(ctx, pck) + ts_diff;
849 : }
850 0 : gf_filter_pid_drop_packet(ctx->in_pid);
851 0 : return GF_SERVICE_ERROR;
852 : }
853 23 : } else if (ctx->samples_in_audio_buffer) {
854 : u32 real_samples = ctx->samples_in_audio_buffer;
855 5 : if (ctx->encoder->frame_size) {
856 5 : nb_samples = ctx->encoder->frame_size - ctx->samples_in_audio_buffer;
857 5 : ffenc_audio_append_samples(ctx, NULL, 0, 0, nb_samples);
858 5 : res = avcodec_fill_audio_frame(ctx->frame, ctx->channels, ctx->sample_fmt, ctx->audio_buffer, ctx->encoder->frame_size * ctx->bytes_per_sample, 0);
859 : } else {
860 0 : res = avcodec_fill_audio_frame(ctx->frame, ctx->channels, ctx->sample_fmt, ctx->audio_buffer, ctx->samples_in_audio_buffer * ctx->bytes_per_sample, 0);
861 : }
862 5 : ctx->frame->nb_samples = real_samples;
863 5 : if (res<0) {
864 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFEnc] Error filling raw audio frame: %s\n", av_err2str(res) ));
865 0 : ctx->samples_in_audio_buffer = 0;
866 : } else {
867 5 : ctx->samples_in_audio_buffer = real_samples;
868 5 : if (ctx->ts_shift && ctx->encoder->frame_size && (ctx->encoder->frame_size>ctx->ts_shift)) {
869 2 : ctx->samples_in_audio_buffer += (u32) ctx->ts_shift;
870 2 : if (ctx->samples_in_audio_buffer > (u32) ctx->encoder->frame_size)
871 0 : ctx->samples_in_audio_buffer = ctx->encoder->frame_size;
872 : }
873 : }
874 : }
875 :
876 1138 : av_init_packet(&pkt);
877 1138 : pkt.data = (uint8_t*)ctx->enc_buffer;
878 1138 : pkt.size = ctx->enc_buffer_size;
879 :
880 1138 : if (pck)
881 1115 : ctx->frame->nb_samples = ctx->encoder->frame_size;
882 1138 : ctx->frame->format = ctx->encoder->sample_fmt;
883 1138 : ctx->frame->channels = ctx->encoder->channels;
884 1138 : ctx->frame->channel_layout = ctx->encoder->channel_layout;
885 1138 : gotpck = 0;
886 1138 : if (pck || ctx->samples_in_audio_buffer) {
887 1120 : ctx->frame->pkt_dts = ctx->frame->pkt_pts = ctx->frame->pts = ctx->first_byte_cts;
888 1120 : res = avcodec_encode_audio2(ctx->encoder, &pkt, ctx->frame, &gotpck);
889 1120 : if (!pck) {
890 5 : if (! (ctx->encoder->codec->capabilities & AV_CODEC_CAP_DELAY)) {
891 2 : pkt.duration = ctx->samples_in_audio_buffer;
892 2 : if (ctx->timescale != ctx->sample_rate) {
893 0 : pkt.duration *= ctx->timescale;
894 0 : pkt.duration /= ctx->sample_rate;
895 : }
896 : }
897 5 : ctx->samples_in_audio_buffer = 0;
898 : }
899 : } else {
900 18 : res = avcodec_encode_audio2(ctx->encoder, &pkt, NULL, &gotpck);
901 18 : if (!gotpck) {
902 : //done flushing encoder while reconfiguring
903 10 : if (ctx->reconfig_pending) {
904 : GF_Err e;
905 2 : Bool bck_init_cts = ctx->init_cts_setup;
906 :
907 2 : ctx->reconfig_pending = GF_FALSE;
908 2 : avcodec_free_context(&ctx->encoder);
909 2 : ctx->encoder = NULL;
910 2 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FFEnc] codec flush done, triggering reconfiguration\n"));
911 2 : e = ffenc_configure_pid_ex(filter, ctx->in_pid, GF_FALSE, GF_TRUE);
912 2 : ctx->init_cts_setup = bck_init_cts;
913 2 : return e;
914 : }
915 8 : ctx->flush_done = 1;
916 8 : gf_filter_pid_set_eos(ctx->out_pid);
917 8 : return GF_EOS;
918 : }
919 : }
920 :
921 1128 : if (from_internal_buffer_only) {
922 : //avcodec_fill_audio_frame does not perform copy, so make sure we discard internal buffer AFTER we encode
923 : u32 offset, len, nb_samples_to_drop;
924 :
925 : //we always drop a complete encoder frame size, so same code for planar and packed
926 0 : nb_samples_to_drop = ctx->encoder->frame_size;
927 :
928 0 : if (ctx->samples_in_audio_buffer > nb_samples_to_drop) {
929 0 : offset = nb_samples_to_drop * ctx->bytes_per_sample;
930 0 : len = (ctx->samples_in_audio_buffer - nb_samples_to_drop) * ctx->bytes_per_sample;
931 0 : memmove(ctx->audio_buffer, ctx->audio_buffer + offset, sizeof(u8)*len);
932 0 : ctx->samples_in_audio_buffer -= nb_samples_to_drop;
933 : } else {
934 0 : ctx->samples_in_audio_buffer = 0;
935 : }
936 :
937 : }
938 :
939 : //increase timestamp
940 1128 : ts_diff = ctx->frame->nb_samples;
941 1128 : if (ctx->timescale!=ctx->sample_rate) {
942 0 : ts_diff *= ctx->timescale;
943 0 : ts_diff /= ctx->sample_rate;
944 : }
945 1128 : ctx->first_byte_cts += ts_diff;
946 :
947 1128 : if (pck && !from_internal_buffer_only) {
948 1115 : ctx->samples_in_audio_buffer = 0;
949 1115 : if (nb_samples > nb_copy) {
950 954 : ffenc_audio_append_samples(ctx, data, size, nb_copy, nb_samples - nb_copy);
951 : }
952 1115 : gf_filter_pid_drop_packet(ctx->in_pid);
953 : }
954 :
955 1128 : if (res<0) {
956 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFEnc] Error encoding frame: %s\n", av_err2str(res) ));
957 0 : av_packet_free_side_data(&pkt);
958 0 : return GF_SERVICE_ERROR;
959 : }
960 1128 : if (!gotpck) {
961 4 : av_packet_free_side_data(&pkt);
962 4 : return GF_OK;
963 : }
964 1124 : dst_pck = gf_filter_pck_new_alloc(ctx->out_pid, pkt.size, &output);
965 1124 : if (!dst_pck) return GF_OUT_OF_MEM;
966 1124 : memcpy(output, pkt.data, pkt.size);
967 :
968 1124 : if (ctx->init_cts_setup) {
969 : u64 octs;
970 8 : ctx->init_cts_setup = GF_FALSE;
971 8 : src_pck = gf_list_get(ctx->src_packets, 0);
972 8 : octs = src_pck ? ffenc_get_cts(ctx, src_pck) : ctx->frame->pts;
973 8 : if (octs != pkt.pts) {
974 8 : ctx->ts_shift = (s64) octs - (s64) pkt.pts;
975 : }
976 8 : if (ctx->ts_shift) {
977 8 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_DELAY, &PROP_LONGSINT( - ctx->ts_shift) );
978 : }
979 : }
980 :
981 : //try to locate first source packet with CTS
982 : //- greater than or equal to this packet cts
983 : //- strictly less than next packet cts
984 : // and use it as source for properties
985 : //this is not optimal because we dont produce N for N because of different window coding sizes
986 1124 : src_pck = NULL;
987 1124 : count = gf_list_count(ctx->src_packets);
988 2026 : for (i=0; i<count; i++) {
989 : u64 acts;
990 : u32 adur;
991 2021 : src_pck = gf_list_get(ctx->src_packets, i);
992 2021 : acts = ffenc_get_cts(ctx, src_pck);
993 2021 : adur = gf_filter_pck_get_duration(src_pck);
994 :
995 2021 : if (((s64) acts >= pkt.pts) && ((s64) acts < pkt.pts + pkt.duration)) {
996 : break;
997 : }
998 :
999 902 : if (acts + adur <= (u64) ( pkt.pts + ctx->ts_shift) ) {
1000 797 : gf_list_rem(ctx->src_packets, i);
1001 797 : gf_filter_pck_unref(src_pck);
1002 797 : i--;
1003 797 : count--;
1004 : }
1005 902 : src_pck = NULL;
1006 : }
1007 1124 : if (src_pck) {
1008 1119 : if (src_pck==ctx->disc_pck_ref) {
1009 0 : ctx->disc_pck_ref = NULL;
1010 0 : ffenc_copy_pid_props(ctx);
1011 : }
1012 :
1013 1119 : gf_filter_pck_merge_properties(src_pck, dst_pck);
1014 1119 : gf_list_del_item(ctx->src_packets, src_pck);
1015 1119 : gf_filter_pck_unref(src_pck);
1016 : }
1017 :
1018 1124 : gf_filter_pck_set_cts(dst_pck, pkt.pts + ctx->ts_shift);
1019 1124 : gf_filter_pck_set_dts(dst_pck, pkt.dts + ctx->ts_shift);
1020 : //this is not 100% correct since we don't have any clue if this is SAP1/4 (roll info missing)
1021 1124 : if (pkt.flags & AV_PKT_FLAG_KEY)
1022 1124 : gf_filter_pck_set_sap(dst_pck, GF_FILTER_SAP_1);
1023 : else
1024 0 : gf_filter_pck_set_sap(dst_pck, 0);
1025 :
1026 1124 : gf_filter_pck_set_duration(dst_pck, (u32) pkt.duration);
1027 :
1028 1124 : gf_filter_pck_send(dst_pck);
1029 :
1030 1124 : av_packet_free_side_data(&pkt);
1031 : //we're in final flush, request a process task until all frames flushe
1032 : //we could recursiveley call ourselves, same result
1033 1124 : if (!pck) {
1034 13 : gf_filter_post_process_task(filter);
1035 : }
1036 : return GF_OK;
1037 : }
1038 :
1039 5083 : static GF_Err ffenc_process(GF_Filter *filter)
1040 : {
1041 5083 : GF_FFEncodeCtx *ctx = (GF_FFEncodeCtx *) gf_filter_get_udta(filter);
1042 5083 : if (!ctx->out_pid || gf_filter_pid_would_block(ctx->out_pid))
1043 : return GF_OK;
1044 5083 : return ctx->process(filter, ctx);
1045 : }
1046 :
1047 62 : static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove, Bool is_force_reconf)
1048 : {
1049 : s32 res;
1050 62 : u32 type=0, fftype, ff_codectag=0;
1051 : u32 i=0;
1052 62 : AVDictionary *options = NULL;
1053 : u32 change_input_fmt = 0;
1054 : const GF_PropertyValue *prop;
1055 : const AVCodec *codec=NULL;
1056 : const AVCodec *desired_codec=NULL;
1057 : u32 codec_id, pfmt, afmt;
1058 62 : GF_FFEncodeCtx *ctx = (GF_FFEncodeCtx *) gf_filter_get_udta(filter);
1059 :
1060 : //disconnect of src pid (not yet supported)
1061 62 : if (is_remove) {
1062 0 : ctx->in_pid = NULL;
1063 0 : if (ctx->out_pid) {
1064 0 : gf_filter_pid_remove(ctx->out_pid);
1065 0 : ctx->out_pid = NULL;
1066 : }
1067 : return GF_OK;
1068 : }
1069 : //check our PID: streamtype and codecid
1070 62 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_STREAM_TYPE);
1071 62 : if (!prop) return GF_NOT_SUPPORTED;
1072 :
1073 62 : type = prop->value.uint;
1074 62 : switch (type) {
1075 : case GF_STREAM_AUDIO:
1076 : case GF_STREAM_VISUAL:
1077 : break;
1078 : default:
1079 : return GF_NOT_SUPPORTED;
1080 : }
1081 62 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
1082 62 : if (!prop || prop->value.uint!=GF_CODECID_RAW) return GF_NOT_SUPPORTED;
1083 :
1084 62 : if (!ctx->force_codec) {
1085 : //figure out if output was preconfigured during filter chain setup
1086 52 : prop = gf_filter_pid_caps_query(pid, GF_PROP_PID_CODECID);
1087 52 : if (prop) {
1088 36 : ctx->codecid = prop->value.uint;
1089 16 : } else if (!ctx->codecid && ctx->c) {
1090 10 : ctx->codecid = gf_codecid_parse(ctx->c);
1091 10 : if (!ctx->codecid) {
1092 0 : codec = avcodec_find_encoder_by_name(ctx->c);
1093 0 : if (codec)
1094 0 : ctx->codecid = ffmpeg_codecid_to_gpac(codec->id);
1095 : }
1096 : }
1097 : } else {
1098 10 : ctx->codecid = ffmpeg_codecid_to_gpac(ctx->force_codec->id);
1099 10 : desired_codec = ctx->force_codec;
1100 : }
1101 :
1102 62 : if (!ctx->codecid && !desired_codec) {
1103 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFEnc] No codecid specified\n" ));
1104 : return GF_BAD_PARAM;
1105 : }
1106 :
1107 : //initial config or update
1108 62 : if (!ctx->in_pid || (ctx->in_pid==pid)) {
1109 62 : ctx->in_pid = pid;
1110 62 : if (!ctx->type) ctx->type = type;
1111 : //no support for dynamic changes of stream types
1112 30 : else if (ctx->type != type) {
1113 : return GF_NOT_SUPPORTED;
1114 : }
1115 : } else {
1116 : //only one input pid in ctx
1117 : if (ctx->in_pid) return GF_REQUIRES_NEW_INSTANCE;
1118 : }
1119 :
1120 62 : if (ctx->codecid) {
1121 62 : codec_id = ffmpeg_codecid_from_gpac(ctx->codecid, &ff_codectag);
1122 62 : if (codec_id) {
1123 62 : if (desired_codec && desired_codec->id==codec_id)
1124 : codec = desired_codec;
1125 : else
1126 52 : codec = avcodec_find_encoder(codec_id);
1127 : }
1128 : } else {
1129 : codec = desired_codec;
1130 : }
1131 62 : if (!codec) {
1132 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFEnc] Cannot find encoder for codec %s\n", gf_codecid_name(ctx->codecid) ));
1133 : return GF_NOT_SUPPORTED;
1134 : }
1135 62 : codec_id = codec->id;
1136 62 : if (!ctx->codecid)
1137 0 : ctx->codecid = ffmpeg_codecid_to_gpac(codec->id);
1138 :
1139 62 : fftype = ffmpeg_stream_type_to_gpac(codec->type);
1140 62 : if (fftype != type) {
1141 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFEnc] Mismatch between stream type, codec indicates %s but source type is %s\n", gf_stream_type_name(fftype), gf_stream_type_name(type) ));
1142 : return GF_NOT_SUPPORTED;
1143 : }
1144 :
1145 : //declare our output pid to make sure we connect the chain
1146 62 : ctx->in_pid = pid;
1147 62 : if (!ctx->out_pid) {
1148 : char szCodecName[1000];
1149 32 : ctx->out_pid = gf_filter_pid_new(filter);
1150 :
1151 : //to change once we implement on-the-fly codec change
1152 32 : sprintf(szCodecName, "ffenc:%s", codec->name ? codec->name : "unknown");
1153 32 : gf_filter_set_name(filter, szCodecName);
1154 32 : gf_filter_pid_set_framing_mode(ctx->in_pid, GF_TRUE);
1155 : }
1156 62 : if (type==GF_STREAM_AUDIO) {
1157 18 : ctx->process = ffenc_process_audio;
1158 : } else {
1159 44 : ctx->process = ffenc_process_video;
1160 : }
1161 :
1162 62 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_TARGET_RATE);
1163 62 : if (prop && prop->value.uint && (prop->value.uint != ctx->target_rate)) {
1164 : char szRate[100];
1165 0 : ctx->target_rate = prop->value.uint;
1166 : snprintf(szRate, 99, "%d", ctx->target_rate);
1167 0 : szRate[99] = 0;
1168 0 : av_dict_set(&ctx->options, "b", szRate, 0);
1169 : }
1170 :
1171 62 : if (!is_force_reconf) {
1172 : //not yet setup or no delay, copy directly props, otherwise signal discontinuity
1173 60 : if (!ctx->encoder || !gf_list_count(ctx->src_packets)) {
1174 60 : ffenc_copy_pid_props(ctx);
1175 : } else {
1176 0 : ctx->discontunity = GF_TRUE;
1177 : }
1178 : }
1179 :
1180 : #define GET_PROP(_a, _code, _name) \
1181 : prop = gf_filter_pid_get_property(pid, _code); \
1182 : if (!prop) {\
1183 : GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[FFEnc] Input %s unknown, waiting for reconfigure\n", _name)); \
1184 : return GF_OK; \
1185 : }\
1186 : _a = prop->value.uint;
1187 :
1188 : pfmt = afmt = 0;
1189 62 : if (type==GF_STREAM_VISUAL) {
1190 44 : GET_PROP(ctx->width, GF_PROP_PID_WIDTH, "width")
1191 44 : GET_PROP(ctx->height, GF_PROP_PID_HEIGHT, "height")
1192 44 : GET_PROP(pfmt, GF_PROP_PID_PIXFMT, "pixel format")
1193 :
1194 40 : prop = gf_filter_pid_caps_query(pid, GF_PROP_PID_STRIDE);
1195 : //keep stride and stride_uv to 0 i fnot set, and recompute from pixel format
1196 40 : if (prop) ctx->stride = prop->value.uint;
1197 40 : prop = gf_filter_pid_caps_query(pid, GF_PROP_PID_STRIDE_UV);
1198 40 : if (prop) ctx->stride_uv = prop->value.uint;
1199 : } else {
1200 18 : GET_PROP(ctx->sample_rate, GF_PROP_PID_SAMPLE_RATE, "sample rate")
1201 18 : GET_PROP(ctx->channels, GF_PROP_PID_NUM_CHANNELS, "nb channels")
1202 18 : GET_PROP(afmt, GF_PROP_PID_AUDIO_FORMAT, "audio format")
1203 : }
1204 :
1205 :
1206 58 : if (ctx->encoder) {
1207 : Bool reuse = GF_FALSE;
1208 14 : codec_id = ffmpeg_codecid_from_gpac(ctx->codecid, &ff_codectag);
1209 :
1210 14 : if ((type==GF_STREAM_AUDIO)
1211 0 : && (ctx->encoder->codec->id==codec_id) && (ctx->encoder->sample_rate==ctx->sample_rate)
1212 0 : && (ctx->encoder->channels==ctx->channels) && (ctx->gpac_audio_fmt == afmt )
1213 : ) {
1214 : reuse = GF_TRUE;
1215 14 : } else if ((ctx->encoder->codec->id==codec_id)
1216 14 : && (ctx->encoder->width==ctx->width) && (ctx->encoder->height==ctx->height)
1217 14 : && (ctx->gpac_pixel_fmt == pfmt)
1218 : ) {
1219 : reuse = GF_TRUE;
1220 : }
1221 : if (reuse) {
1222 : //delay may have change
1223 14 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_DELAY);
1224 14 : ctx->in_tk_delay = prop ? prop->value.longsint : 0;
1225 14 : return GF_OK;
1226 : }
1227 :
1228 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FFEnc] codec reconfiguration, beginning flush\n"));
1229 0 : ctx->reconfig_pending = GF_TRUE;
1230 0 : return GF_OK;
1231 : }
1232 :
1233 44 : if (type==GF_STREAM_VISUAL) {
1234 : u32 force_pfmt = AV_PIX_FMT_NONE;
1235 26 : if (ctx->pfmt) {
1236 0 : u32 ff_pfmt = ffmpeg_pixfmt_from_gpac(ctx->pfmt);
1237 : i=0;
1238 0 : while (codec->pix_fmts) {
1239 0 : if (codec->pix_fmts[i] == AV_PIX_FMT_NONE) break;
1240 0 : if (codec->pix_fmts[i] == ff_pfmt) {
1241 : force_pfmt = ff_pfmt;
1242 : break;
1243 : }
1244 : //handle pixel formats aliases
1245 0 : if (ffmpeg_pixfmt_to_gpac(codec->pix_fmts[i]) == ctx->pfmt) {
1246 0 : force_pfmt = ctx->pixel_fmt;
1247 0 : break;
1248 : }
1249 0 : i++;
1250 : }
1251 0 : if (force_pfmt == AV_PIX_FMT_NONE) {
1252 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FFEnc] Requested source format %s not supported by codec, using default one\n", gf_pixel_fmt_name(ctx->pfmt) ));
1253 : } else {
1254 : change_input_fmt = force_pfmt;
1255 : }
1256 : }
1257 26 : ctx->pixel_fmt = ffmpeg_pixfmt_from_gpac(pfmt);
1258 : //check pixel format
1259 26 : if (force_pfmt == AV_PIX_FMT_NONE) {
1260 : change_input_fmt = AV_PIX_FMT_NONE;
1261 : i=0;
1262 38 : while (codec->pix_fmts) {
1263 38 : if (codec->pix_fmts[i] == AV_PIX_FMT_NONE) break;
1264 36 : if (codec->pix_fmts[i] == ctx->pixel_fmt) {
1265 22 : change_input_fmt = ctx->pixel_fmt;
1266 22 : break;
1267 : }
1268 : //handle pixel formats aliases
1269 14 : if (ffmpeg_pixfmt_to_gpac(codec->pix_fmts[i]) == pfmt) {
1270 2 : ctx->pixel_fmt = change_input_fmt = codec->pix_fmts[i];
1271 2 : break;
1272 : }
1273 12 : i++;
1274 : }
1275 26 : if (!ctx->force_codec && (change_input_fmt == AV_PIX_FMT_NONE)) {
1276 : #if (LIBAVCODEC_VERSION_MAJOR >= 58) && (LIBAVCODEC_VERSION_MINOR>=20)
1277 : void *ff_opaque=NULL;
1278 : #else
1279 : AVCodec *codec_alt = NULL;
1280 : #endif
1281 : while (1) {
1282 : #if (LIBAVCODEC_VERSION_MAJOR >= 58) && (LIBAVCODEC_VERSION_MINOR>=20)
1283 : const AVCodec *codec_alt = av_codec_iterate(&ff_opaque);
1284 : #else
1285 1290 : codec_alt = av_codec_next(codec_alt);
1286 : #endif
1287 1290 : if (!codec_alt) break;
1288 1288 : if (codec_alt==codec) continue;
1289 1286 : if (codec_alt->id == codec_id) {
1290 : i=0;
1291 16 : while (codec_alt->pix_fmts) {
1292 14 : if (codec_alt->pix_fmts[i] == AV_PIX_FMT_NONE) break;
1293 10 : if (codec_alt->pix_fmts[i] == ctx->pixel_fmt) {
1294 0 : change_input_fmt = ctx->pixel_fmt;
1295 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FFEnc] Reassigning codec from %s to %s to match pixel format\n", codec->name, codec_alt->name ));
1296 : codec = codec_alt;
1297 : break;
1298 : }
1299 10 : i++;
1300 : }
1301 : }
1302 : }
1303 : }
1304 : }
1305 :
1306 26 : if (ctx->pixel_fmt != change_input_fmt) {
1307 : u32 ff_pmft = ctx->pixel_fmt;
1308 :
1309 2 : if (force_pfmt == AV_PIX_FMT_NONE) {
1310 : ff_pmft = AV_PIX_FMT_NONE;
1311 : i=0;
1312 : //find a mapped pixel format
1313 2 : while (codec->pix_fmts) {
1314 2 : if (codec->pix_fmts[i] == AV_PIX_FMT_NONE) break;
1315 2 : if (ffmpeg_pixfmt_to_gpac(codec->pix_fmts[i])) {
1316 2 : ff_pmft = codec->pix_fmts[i];
1317 2 : break;
1318 : }
1319 0 : i++;
1320 : }
1321 2 : if (ff_pmft == AV_PIX_FMT_NONE) {
1322 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFEnc] Could not find a matching GPAC pixel format for encoder %s\n", codec->name ));
1323 : return GF_NOT_SUPPORTED;
1324 : }
1325 0 : } else if (ctx->pfmt) {
1326 0 : ff_pmft = ffmpeg_pixfmt_from_gpac(ctx->pfmt);
1327 : }
1328 2 : pfmt = ffmpeg_pixfmt_to_gpac(ff_pmft);
1329 2 : gf_filter_pid_negociate_property(ctx->in_pid, GF_PROP_PID_PIXFMT, &PROP_UINT(pfmt) );
1330 2 : ctx->infmt_negociate = GF_TRUE;
1331 : } else {
1332 24 : ctx->infmt_negociate = GF_FALSE;
1333 : }
1334 : } else {
1335 : u32 change_input_sr = 0;
1336 : //check audio format
1337 18 : ctx->sample_fmt = ffmpeg_audio_fmt_from_gpac(afmt);
1338 : change_input_fmt = 0;
1339 44 : while (codec->sample_fmts) {
1340 26 : if (codec->sample_fmts[i] == AV_SAMPLE_FMT_NONE) break;
1341 18 : if (codec->sample_fmts[i] == ctx->sample_fmt) {
1342 : change_input_fmt = ctx->sample_fmt;
1343 : break;
1344 : }
1345 8 : i++;
1346 : }
1347 : i=0;
1348 18 : if (!codec->supported_samplerates)
1349 4 : change_input_sr = ctx->sample_rate;
1350 :
1351 92 : while (codec->supported_samplerates) {
1352 88 : if (!codec->supported_samplerates[i]) break;
1353 88 : if (codec->supported_samplerates[i]==ctx->sample_rate) {
1354 : change_input_sr = ctx->sample_rate;
1355 : break;
1356 : }
1357 74 : i++;
1358 : }
1359 18 : if ((ctx->sample_fmt != change_input_fmt) || (ctx->sample_rate != change_input_sr)) {
1360 8 : if (ctx->sample_fmt != change_input_fmt) {
1361 8 : ctx->sample_fmt = codec->sample_fmts ? codec->sample_fmts[0] : AV_SAMPLE_FMT_S16;
1362 8 : afmt = ffmpeg_audio_fmt_to_gpac(ctx->sample_fmt);
1363 8 : gf_filter_pid_negociate_property(ctx->in_pid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(afmt) );
1364 : }
1365 8 : if (ctx->sample_rate != change_input_sr) {
1366 0 : gf_filter_pid_negociate_property(ctx->in_pid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT(codec->supported_samplerates[0]) );
1367 : }
1368 8 : ctx->infmt_negociate = GF_TRUE;
1369 : } else {
1370 10 : ctx->infmt_negociate = GF_FALSE;
1371 : }
1372 : }
1373 :
1374 : //renegociate input, wait for reconfig call
1375 44 : if (ctx->infmt_negociate) return GF_OK;
1376 :
1377 34 : ctx->gpac_pixel_fmt = pfmt;
1378 34 : ctx->gpac_audio_fmt = afmt;
1379 34 : ctx->dsi_crc = 0;
1380 :
1381 34 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_DELAY);
1382 34 : ctx->in_tk_delay = prop ? prop->value.longsint : 0;
1383 :
1384 34 : ctx->encoder = avcodec_alloc_context3(codec);
1385 34 : if (! ctx->encoder) return GF_OUT_OF_MEM;
1386 :
1387 34 : ctx->encoder->codec_tag = ff_codectag;
1388 34 : if (type==GF_STREAM_VISUAL) {
1389 24 : ctx->encoder->width = ctx->width;
1390 24 : ctx->encoder->height = ctx->height;
1391 24 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_SAR);
1392 24 : if (prop) {
1393 13 : ctx->encoder->sample_aspect_ratio.num = prop->value.frac.num;
1394 13 : ctx->timescale = ctx->encoder->sample_aspect_ratio.den = prop->value.frac.den;
1395 : } else {
1396 11 : ctx->encoder->sample_aspect_ratio.num = 1;
1397 11 : ctx->encoder->sample_aspect_ratio.den = 1;
1398 : }
1399 : //CHECKME: do we need to use 1/FPS ?
1400 24 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_TIMESCALE);
1401 24 : if (prop) {
1402 24 : ctx->encoder->time_base.num = 1;
1403 24 : ctx->timescale = ctx->encoder->time_base.den = prop->value.uint;
1404 : }
1405 24 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_FPS);
1406 24 : if (prop) {
1407 22 : ctx->encoder->gop_size = prop->value.frac.num / prop->value.frac.den;
1408 22 : ctx->encoder->time_base.num = prop->value.frac.den;
1409 22 : ctx->encoder->time_base.den = prop->value.frac.num;
1410 : }
1411 :
1412 24 : gf_media_get_reduced_frame_rate(&ctx->encoder->time_base.den, &ctx->encoder->time_base.num);
1413 :
1414 24 : if (ctx->low_delay) {
1415 0 : av_dict_set(&ctx->options, "profile", "baseline", 0);
1416 0 : av_dict_set(&ctx->options, "preset", "ultrafast", 0);
1417 0 : av_dict_set(&ctx->options, "tune", "zerolatency", 0);
1418 0 : if (ctx->codecid==GF_CODECID_AVC) {
1419 0 : av_dict_set(&ctx->options, "x264opts", "no-mbtree:sliced-threads:sync-lookahead=0", 0);
1420 : }
1421 : #if LIBAVCODEC_VERSION_MAJOR >= 58
1422 : ctx->encoder->flags |= AV_CODEC_FLAG_LOW_DELAY;
1423 : #endif
1424 : }
1425 :
1426 24 : if (ctx->fintra.den && (ctx->fintra.num>0) && !ctx->rc) {
1427 8 : av_dict_set(&ctx->options, "forced-idr", "1", 0);
1428 : }
1429 :
1430 : //we don't use out of band headers, since x264 in ffmpeg (and likely other) do not output in MP4 format but
1431 : //in annexB (extradata only contains SPS/PPS/etc in annexB)
1432 : //so we indicate unframed for these codecs and use our own filter for annexB->MP4
1433 :
1434 24 : if (!ctx->frame)
1435 24 : ctx->frame = av_frame_alloc();
1436 :
1437 24 : ctx->enc_buffer_size = ctx->width*ctx->height + ENC_BUF_ALLOC_SAFE;
1438 24 : ctx->enc_buffer = gf_realloc(ctx->enc_buffer, sizeof(char)*ctx->enc_buffer_size);
1439 :
1440 24 : gf_pixel_get_size_info(pfmt, ctx->width, ctx->height, NULL, &ctx->stride, &ctx->stride_uv, &ctx->nb_planes, &ctx->uv_height);
1441 :
1442 24 : ctx->encoder->pix_fmt = ctx->pixel_fmt;
1443 24 : ctx->init_cts_setup = GF_TRUE;
1444 24 : ctx->frame->format = ctx->encoder->pix_fmt;
1445 10 : } else if (type==GF_STREAM_AUDIO) {
1446 10 : ctx->process = ffenc_process_audio;
1447 :
1448 10 : ctx->encoder->sample_rate = ctx->sample_rate;
1449 10 : ctx->encoder->channels = ctx->channels;
1450 :
1451 : //TODO
1452 10 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CHANNEL_LAYOUT);
1453 10 : if (prop) {
1454 10 : ctx->encoder->channel_layout = ffmpeg_channel_layout_from_gpac(prop->value.longuint);
1455 0 : } else if (ctx->channels==1) {
1456 0 : ctx->encoder->channel_layout = AV_CH_LAYOUT_MONO;
1457 0 : } else if (ctx->channels==2) {
1458 0 : ctx->encoder->channel_layout = AV_CH_LAYOUT_STEREO;
1459 : }
1460 :
1461 10 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_TIMESCALE);
1462 10 : if (prop) {
1463 10 : ctx->encoder->time_base.num = 1;
1464 10 : ctx->encoder->time_base.den = prop->value.uint;
1465 10 : ctx->timescale = prop->value.uint;
1466 : } else {
1467 0 : ctx->encoder->time_base.num = 1;
1468 0 : ctx->encoder->time_base.den = ctx->sample_rate;
1469 0 : ctx->timescale = ctx->sample_rate;
1470 : }
1471 :
1472 : //for aac
1473 10 : switch (ctx->codecid) {
1474 6 : case GF_CODECID_AAC_MPEG4:
1475 : case GF_CODECID_AAC_MPEG2_MP:
1476 : case GF_CODECID_AAC_MPEG2_LCP:
1477 : case GF_CODECID_AAC_MPEG2_SSRP:
1478 6 : av_dict_set(&ctx->options, "strict", "experimental", 0);
1479 6 : break;
1480 : }
1481 :
1482 10 : if (!ctx->frame)
1483 8 : ctx->frame = av_frame_alloc();
1484 :
1485 10 : ctx->enc_buffer_size = ctx->channels*ctx->sample_rate + ENC_BUF_ALLOC_SAFE;
1486 10 : ctx->enc_buffer = gf_realloc(ctx->enc_buffer, sizeof(char) * ctx->enc_buffer_size);
1487 :
1488 10 : ctx->encoder->sample_fmt = ctx->sample_fmt;
1489 10 : ctx->planar_audio = gf_audio_fmt_is_planar(afmt);
1490 10 : ctx->frame->format = ctx->encoder->sample_fmt;
1491 :
1492 10 : ctx->audio_buffer_size = ctx->sample_rate;
1493 10 : ctx->audio_buffer = gf_realloc(ctx->audio_buffer, sizeof(char) * ctx->enc_buffer_size);
1494 10 : ctx->bytes_per_sample = ctx->channels * gf_audio_fmt_bit_depth(afmt) / 8;
1495 10 : ctx->init_cts_setup = GF_TRUE;
1496 :
1497 10 : switch (ctx->codecid) {
1498 6 : case GF_CODECID_AAC_MPEG4:
1499 : case GF_CODECID_AAC_MPEG2_MP:
1500 : case GF_CODECID_AAC_MPEG2_LCP:
1501 : case GF_CODECID_AAC_MPEG2_SSRP:
1502 6 : if (!is_force_reconf) {
1503 : #ifndef GPAC_DISABLE_AV_PARSERS
1504 : GF_M4ADecSpecInfo acfg;
1505 : u8 *dsi;
1506 : u32 dsi_len;
1507 : memset(&acfg, 0, sizeof(GF_M4ADecSpecInfo));
1508 4 : acfg.base_object_type = GF_M4A_AAC_LC;
1509 4 : acfg.base_sr = ctx->sample_rate;
1510 4 : acfg.nb_chan = ctx->channels;
1511 : acfg.sbr_object_type = 0;
1512 4 : acfg.audioPL = gf_m4a_get_profile(&acfg);
1513 :
1514 4 : gf_m4a_write_config(&acfg, &dsi, &dsi_len);
1515 4 : gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_len) );
1516 : #endif
1517 : }
1518 : break;
1519 : }
1520 : }
1521 :
1522 34 : ffmpeg_set_enc_dec_flags(ctx->options, ctx->encoder);
1523 :
1524 34 : if (ctx->all_intra) ctx->encoder->gop_size = 0;
1525 34 : else if (ctx->gop_size) ctx->encoder->gop_size = ctx->gop_size;
1526 :
1527 : //by default let libavcodec decide - if single thread is required, let the user define -threads option
1528 34 : if (codec->capabilities & AV_CODEC_CAP_AUTO_THREADS)
1529 10 : ctx->encoder->thread_count = 0;
1530 :
1531 :
1532 34 : av_dict_copy(&options, ctx->options, 0);
1533 34 : res = avcodec_open2(ctx->encoder, codec, &options );
1534 34 : if (res < 0) {
1535 0 : if (options) av_dict_free(&options);
1536 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFEnc] PID %s failed to open codec context: %s\n", gf_filter_pid_get_name(pid), av_err2str(res) ));
1537 : return GF_BAD_PARAM;
1538 : }
1539 34 : ctx->remap_ts = (ctx->encoder->time_base.den && (ctx->encoder->time_base.den != ctx->timescale)) ? GF_TRUE : GF_FALSE;
1540 34 : if (!ctx->target_rate)
1541 30 : ctx->target_rate = (u32)ctx->encoder->bit_rate;
1542 :
1543 34 : if (options) {
1544 2 : ffmpeg_report_unused_options(filter, options);
1545 2 : av_dict_free(&options);
1546 : }
1547 :
1548 34 : if (!is_force_reconf)
1549 32 : ffenc_copy_pid_props(ctx);
1550 : return GF_OK;
1551 : }
1552 :
1553 60 : static GF_Err ffenc_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
1554 : {
1555 60 : return ffenc_configure_pid_ex(filter, pid, is_remove, GF_FALSE);
1556 :
1557 : }
1558 :
1559 :
1560 8 : static GF_Err ffenc_update_arg(GF_Filter *filter, const char *arg_name, const GF_PropertyValue *arg_val)
1561 : {
1562 : s32 res;
1563 : char szOverrideOpt[1000];
1564 : Bool do_override = GF_FALSE;
1565 8 : GF_FFEncodeCtx *ctx = gf_filter_get_udta(filter);
1566 :
1567 8 : if (!strcmp(arg_name, "global_header")) return GF_OK;
1568 8 : else if (!strcmp(arg_name, "local_header")) return GF_OK;
1569 8 : else if (!strcmp(arg_name, "low_delay")) ctx->low_delay = GF_TRUE;
1570 : //remap some options
1571 8 : else if (!strcmp(arg_name, "bitrate") || !strcmp(arg_name, "rate")) arg_name = "b";
1572 : // else if (!strcmp(arg_name, "gop")) arg_name = "g";
1573 : //disable low delay if these options are set
1574 8 : else if (!strcmp(arg_name, "x264opts")) ctx->low_delay = GF_FALSE;
1575 8 : else if (!strcmp(arg_name, "profile")) ctx->low_delay = GF_FALSE;
1576 6 : else if (!strcmp(arg_name, "preset")) ctx->low_delay = GF_FALSE;
1577 6 : else if (!strcmp(arg_name, "tune")) ctx->low_delay = GF_FALSE;
1578 :
1579 8 : if (!strcmp(arg_name, "g") || !strcmp(arg_name, "gop"))
1580 0 : ctx->gop_size = arg_val->value.string ? atoi(arg_val->value.string) : 25;
1581 :
1582 8 : if (!strcmp(arg_name, "b") && arg_val->value.string) {
1583 2 : ctx->target_rate = atoi(arg_val->value.string);
1584 2 : if (strchr(arg_val->value.string, 'm') || strchr(arg_val->value.string, 'M'))
1585 0 : ctx->target_rate *= 1000000;
1586 2 : else if (strchr(arg_val->value.string, 'k') || strchr(arg_val->value.string, 'K'))
1587 2 : ctx->target_rate *= 1000;
1588 :
1589 2 : sprintf(szOverrideOpt, "%d", ctx->target_rate);
1590 : do_override = GF_TRUE;
1591 : }
1592 :
1593 : //initial parsing of arguments
1594 8 : if (!ctx->initialized) {
1595 : const char *arg_val_str;
1596 8 : switch (arg_val->type) {
1597 8 : case GF_PROP_STRING:
1598 8 : if (do_override)
1599 : arg_val_str = szOverrideOpt;
1600 : else {
1601 6 : arg_val_str = arg_val->value.string;
1602 6 : if (!arg_val_str) arg_val_str = "1";
1603 : }
1604 8 : res = av_dict_set(&ctx->options, arg_name, arg_val_str, 0);
1605 8 : if (res<0) {
1606 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFEnc] Failed to set option %s:%s\n", arg_name, arg_val ));
1607 : }
1608 : break;
1609 0 : default:
1610 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFEnc] Failed to set option %s:%s, unrecognized type %d\n", arg_name, arg_val, arg_val->type ));
1611 : return GF_NOT_SUPPORTED;
1612 : }
1613 : return GF_OK;
1614 : }
1615 : //updates of arguments, not supported for ffmpeg decoders
1616 : return GF_NOT_SUPPORTED;
1617 : }
1618 :
1619 1025 : static Bool ffenc_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
1620 : {
1621 1025 : if (evt->base.type==GF_FEVT_ENCODE_HINTS) {
1622 32 : GF_FFEncodeCtx *ctx = gf_filter_get_udta(filter);
1623 32 : if ((ctx->fintra.num<0) && evt->encode_hints.intra_period.den && evt->encode_hints.intra_period.num) {
1624 2 : ctx->fintra = evt->encode_hints.intra_period;
1625 2 : if (!ctx->rc || (gf_list_count(ctx->src_packets) && !ctx->force_reconfig)) {
1626 2 : ctx->reconfig_pending = GF_TRUE;
1627 2 : ctx->force_reconfig = GF_TRUE;
1628 : }
1629 : }
1630 : return GF_TRUE;
1631 : }
1632 : return GF_FALSE;
1633 : }
1634 :
1635 : static const GF_FilterCapability FFEncodeCaps[] =
1636 : {
1637 : CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
1638 : CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
1639 : CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
1640 : CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW),
1641 : CAP_BOOL(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_TILE_BASE, GF_TRUE),
1642 : //some video encoding dumps in unframe mode, we declare the pid property at runtime
1643 : {0},
1644 : CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
1645 : CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
1646 : CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
1647 : CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW),
1648 : };
1649 :
1650 : GF_FilterRegister FFEncodeRegister = {
1651 : .name = "ffenc",
1652 : .version=LIBAVCODEC_IDENT,
1653 : GF_FS_SET_DESCRIPTION("FFMPEG encoder")
1654 : GF_FS_SET_HELP("Encodes audio and video streams.\n"
1655 : "See FFMPEG documentation (https://ffmpeg.org/documentation.html) for more details.\n"
1656 : "To list all supported encoders for your GPAC build, use `gpac -h ffenc:*`.\n"
1657 : "\n"
1658 : "The filter will try to resolve the codec name in [-c]() against a libavcodec codec name (eg `libx264`) and use it if found.\n"
1659 : "If not found, it will consider the name to be a GPAC codec name and find a codec for it. In that case, if no pixel format is given, codecs will be enumerated to find a matching pixel format.\n"
1660 : "\n"
1661 : "Options can be passed from prompt using `-+OPT=VAL` (global options) or appending `::OPT=VAL` to the desired encoder filter.\n"
1662 : "\n"
1663 : "The filter will look for property `TargetRate` on input PID to set the desired bitrate per PID.\n"
1664 : "\n"
1665 : "The filter will force a closed gop boundary:\n"
1666 : "- at each packet with a `FileNumber` property set or a `CueStart` property set to true.\n"
1667 : "- if [-fintra]() and [-rc]() is set.\n"
1668 : "When forcing a closed GOP boundary, the filter will flush, destroy and recreate the encoder to make sure a clean context is used, as currently many encoders in libavcodec do not support clean reset when forcing picture types.\n"
1669 : "If [-fintra]() is not set and the output of the encoder is a DASH session in live profile without segment timeline, [-fintra]() will be set to the target segment duration and [-rc]() will be set.\n"
1670 : )
1671 : .private_size = sizeof(GF_FFEncodeCtx),
1672 : SETCAPS(FFEncodeCaps),
1673 : .initialize = ffenc_initialize,
1674 : .finalize = ffenc_finalize,
1675 : .configure_pid = ffenc_configure_pid,
1676 : .process = ffenc_process,
1677 : .process_event = ffenc_process_event,
1678 : .update_arg = ffenc_update_arg,
1679 : .flags = GF_FS_REG_META,
1680 : };
1681 :
1682 : #define OFFS(_n) #_n, offsetof(GF_FFEncodeCtx, _n)
1683 : static const GF_FilterArgs FFEncodeArgs[] =
1684 : {
1685 : { OFFS(c), "codec identifier. Can be any supported GPAC codec name or ffmpeg codec name", GF_PROP_STRING, NULL, NULL, 0},
1686 : { OFFS(pfmt), "pixel format for input video. When not set, input format is used", GF_PROP_PIXFMT, "none", NULL, 0},
1687 : { OFFS(fintra), "force intra / IDR frames at the given period in sec, eg `fintra=60000/1001` will force an intra every 2 seconds on 29.97 fps video; ignored for audio", GF_PROP_FRACTION, "-1/1", NULL, 0},
1688 :
1689 : { OFFS(all_intra), "only produce intra frames", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_UPDATE|GF_FS_ARG_HINT_ADVANCED},
1690 : { OFFS(ls), "log stats", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
1691 : { OFFS(rc), "reset encoder when forcing intra frame (some encoders might not support intra frame forcing)", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
1692 :
1693 : { "*", -1, "any possible options defined for AVCodecContext and sub-classes. see `gpac -hx ffenc` and `gpac -hx ffenc:*`", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_META},
1694 : {0}
1695 : };
1696 :
1697 : const int FFENC_STATIC_ARGS = (sizeof (FFEncodeArgs) / sizeof (GF_FilterArgs)) - 1;
1698 :
1699 2877 : const GF_FilterRegister *ffenc_register(GF_FilterSession *session)
1700 : {
1701 2877 : ffmpeg_build_register(session, &FFEncodeRegister, FFEncodeArgs, FFENC_STATIC_ARGS, FF_REG_TYPE_ENCODE);
1702 2877 : return &FFEncodeRegister;
1703 : }
1704 :
1705 :
1706 : #else
1707 : #include <gpac/filters.h>
1708 : const GF_FilterRegister *ffenc_register(GF_FilterSession *session)
1709 : {
1710 : return NULL;
1711 : }
1712 :
1713 : #endif //GPAC_HAS_FFMPEG
1714 :
|