int ff_audio_rechunk_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush, int (*get_packet)(AVFormatContext *, AVPacket *, AVPacket *, int), int (*compare_ts)(AVFormatContext *, AVPacket *, AVPacket *)) { int i, ret; if (pkt) { AVStream *st = s->streams[pkt->stream_index]; AudioInterleaveContext *aic = st->priv_data; if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { unsigned new_size = av_fifo_size(aic->fifo) + pkt->size; if (new_size > aic->fifo_size) { if (av_fifo_realloc2(aic->fifo, new_size) < 0) return AVERROR(ENOMEM); aic->fifo_size = new_size; } av_fifo_generic_write(aic->fifo, pkt->data, pkt->size, NULL); } else { // rewrite pts and dts to be decoded time line position pkt->pts = pkt->dts = aic->dts; aic->dts += pkt->duration; if ((ret = ff_interleave_add_packet(s, pkt, compare_ts)) < 0) return ret; } pkt = NULL; } for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { AVPacket new_pkt = { 0 }; while ((ret = interleave_new_audio_packet(s, &new_pkt, i, flush)) > 0) { if ((ret = ff_interleave_add_packet(s, &new_pkt, compare_ts)) < 0) return ret; } if (ret < 0) return ret; } } return get_packet(s, out, NULL, flush); }
int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush) { AVPacketList *pktl; int stream_count = 0; int i, ret; if (pkt) { if ((ret = ff_interleave_add_packet(s, pkt, interleave_compare_dts)) < 0) return ret; } if (s->max_interleave_delta > 0 && s->internal->packet_buffer && !flush) { AVPacket *top_pkt = &s->internal->packet_buffer->pkt; int64_t delta_dts = INT64_MIN; int64_t top_dts = av_rescale_q(top_pkt->dts, s->streams[top_pkt->stream_index]->time_base, AV_TIME_BASE_Q); for (i = 0; i < s->nb_streams; i++) { int64_t last_dts; const AVPacketList *last = s->streams[i]->last_in_packet_buffer; if (!last) continue; last_dts = av_rescale_q(last->pkt.dts, s->streams[i]->time_base, AV_TIME_BASE_Q); delta_dts = FFMAX(delta_dts, last_dts - top_dts); stream_count++; } if (delta_dts > s->max_interleave_delta) { av_log(s, AV_LOG_DEBUG, "Delay between the first packet and last packet in the " "muxing queue is %"PRId64" > %"PRId64": forcing output\n", delta_dts, s->max_interleave_delta); flush = 1; } } else { for (i = 0; i < s->nb_streams; i++) stream_count += !!s->streams[i]->last_in_packet_buffer; } if (stream_count && (s->internal->nb_interleaved_streams == stream_count || flush)) { pktl = s->internal->packet_buffer; *out = pktl->pkt; s->internal->packet_buffer = pktl->next; if (!s->internal->packet_buffer) s->internal->packet_buffer_end = NULL; if (s->streams[out->stream_index]->last_in_packet_buffer == pktl) s->streams[out->stream_index]->last_in_packet_buffer = NULL; av_freep(&pktl); return 1; } else { av_init_packet(out); return 0; } }