static int output_packet(AVFormatContext *ctx, int flush){ MpegMuxContext *s = ctx->priv_data; AVStream *st; StreamInfo *stream; int i, avail_space=0, es_size, trailer_size; int best_i= -1; int best_score= INT_MIN; int ignore_constraints=0; int64_t scr= s->last_scr; PacketDesc *timestamp_packet; const int64_t max_delay= av_rescale(ctx->max_delay, 90000, AV_TIME_BASE); retry: for(i=0; i<ctx->nb_streams; i++){ AVStream *st = ctx->streams[i]; StreamInfo *stream = st->priv_data; const int avail_data= av_fifo_size(stream->fifo); const int space= stream->max_buffer_size - stream->buffer_index; int rel_space= 1024LL*space / stream->max_buffer_size; PacketDesc *next_pkt= stream->premux_packet; /* for subtitle, a single PES packet must be generated, so we flush after every single subtitle packet */ if(s->packet_size > avail_data && !flush && st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) return 0; if(avail_data==0) continue; av_assert0(avail_data>0); if(space < s->packet_size && !ignore_constraints) continue; if(next_pkt && next_pkt->dts - scr > max_delay) continue; if(rel_space > best_score){ best_score= rel_space; best_i = i; avail_space= space; } } if(best_i < 0){ int64_t best_dts= INT64_MAX; for(i=0; i<ctx->nb_streams; i++){ AVStream *st = ctx->streams[i]; StreamInfo *stream = st->priv_data; PacketDesc *pkt_desc= stream->predecode_packet; if(pkt_desc && pkt_desc->dts < best_dts) best_dts= pkt_desc->dts; } av_dlog(ctx, "bumping scr, scr:%f, dts:%f\n", scr / 90000.0, best_dts / 90000.0); if(best_dts == INT64_MAX) return 0; if(scr >= best_dts+1 && !ignore_constraints){ av_log(ctx, AV_LOG_ERROR, "packet too large, ignoring buffer limits to mux it\n"); ignore_constraints= 1; } scr= FFMAX(best_dts+1, scr); if(remove_decoded_packets(ctx, scr) < 0) return -1; goto retry; } assert(best_i >= 0); st = ctx->streams[best_i]; stream = st->priv_data; assert(av_fifo_size(stream->fifo) > 0); assert(avail_space >= s->packet_size || ignore_constraints); timestamp_packet= stream->premux_packet; if(timestamp_packet->unwritten_size == timestamp_packet->size){ trailer_size= 0; }else{ trailer_size= timestamp_packet->unwritten_size; timestamp_packet= timestamp_packet->next; } if(timestamp_packet){ av_dlog(ctx, "dts:%f pts:%f scr:%f stream:%d\n", timestamp_packet->dts / 90000.0, timestamp_packet->pts / 90000.0, scr / 90000.0, best_i); es_size= flush_packet(ctx, best_i, timestamp_packet->pts, timestamp_packet->dts, scr, trailer_size); }else{ assert(av_fifo_size(stream->fifo) == trailer_size); es_size= flush_packet(ctx, best_i, AV_NOPTS_VALUE, AV_NOPTS_VALUE, scr, trailer_size); } if (s->is_vcd) { /* Write one or more padding sectors, if necessary, to reach the constant overall bitrate.*/ int vcd_pad_bytes; while((vcd_pad_bytes = get_vcd_padding_size(ctx,stream->premux_packet->pts) ) >= s->packet_size){ //FIXME pts cannot be correct here put_vcd_padding_sector(ctx); s->last_scr += s->packet_size*90000LL / (s->mux_rate*50LL); //FIXME rounding and first few bytes of each packet } } stream->buffer_index += es_size; s->last_scr += s->packet_size*90000LL / (s->mux_rate*50LL); //FIXME rounding and first few bytes of each packet while(stream->premux_packet && stream->premux_packet->unwritten_size <= es_size){ es_size -= stream->premux_packet->unwritten_size; stream->premux_packet= stream->premux_packet->next; } if(es_size) stream->premux_packet->unwritten_size -= es_size; if(remove_decoded_packets(ctx, s->last_scr) < 0) return -1; return 1; }