static int output_packet(InputStream *ist, int ist_index, OutputStream *ost_table, int nb_ostreams, const AVPacket *pkt) { AVFormatContext *os; OutputStream *ost; int ret, i; int got_output; void *buffer_to_free = NULL; static unsigned int samples_size= 0; AVSubtitle subtitle, *subtitle_to_free; int64_t pkt_pts = AV_NOPTS_VALUE; #if CONFIG_AVFILTER int frame_available; #endif float quality; AVPacket avpkt; int bps = av_get_bytes_per_sample(ist->st->codec->sample_fmt); if(ist->next_pts == AV_NOPTS_VALUE) ist->next_pts= ist->pts; if (pkt == NULL) { /* EOF handling */ av_init_packet(&avpkt); avpkt.data = NULL; avpkt.size = 0; goto handle_eof; } else { avpkt = *pkt; } if(pkt->dts != AV_NOPTS_VALUE) ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); if(pkt->pts != AV_NOPTS_VALUE) pkt_pts = av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q); //while we have more to decode or while the decoder did output something on EOF while (avpkt.size > 0 || (!pkt && got_output)) { uint8_t *data_buf, *decoded_data_buf; int data_size, decoded_data_size; AVFrame *decoded_frame, *filtered_frame; handle_eof: ist->pts= ist->next_pts; if(avpkt.size && avpkt.size != pkt->size) av_log(NULL, ist->showed_multi_packet_warning ? AV_LOG_VERBOSE : AV_LOG_WARNING, "Multiple frames in a packet from stream %d\n", pkt->stream_index); ist->showed_multi_packet_warning=1; /* decode the packet if needed */ decoded_frame = filtered_frame = NULL; decoded_data_buf = NULL; /* fail safe */ decoded_data_size= 0; data_buf = avpkt.data; data_size = avpkt.size; subtitle_to_free = NULL; if (ist->decoding_needed) { switch(ist->st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO:{ if(pkt && samples_size < FFMAX(pkt->size * bps, AVCODEC_MAX_AUDIO_FRAME_SIZE)) { samples_size = FFMAX(pkt->size * bps, AVCODEC_MAX_AUDIO_FRAME_SIZE); av_free(samples); samples= av_malloc(samples_size); } decoded_data_size= samples_size; /* XXX: could avoid copy if PCM 16 bits with same endianness as CPU */ ret = avcodec_decode_audio3(ist->st->codec, samples, &decoded_data_size, &avpkt); if (ret < 0) return ret; avpkt.data += ret; avpkt.size -= ret; data_size = ret; got_output = decoded_data_size > 0; /* Some bug in mpeg audio decoder gives */ /* decoded_data_size < 0, it seems they are overflows */ if (!got_output) { /* no audio frame */ continue; } decoded_data_buf = (uint8_t *)samples; ist->next_pts += ((int64_t)AV_TIME_BASE/bps * decoded_data_size) / (ist->st->codec->sample_rate * ist->st->codec->channels); break;} case AVMEDIA_TYPE_VIDEO: decoded_data_size = (ist->st->codec->width * ist->st->codec->height * 3) / 2; if (!(decoded_frame = avcodec_alloc_frame())) return AVERROR(ENOMEM); avpkt.pts = pkt_pts; avpkt.dts = ist->pts; pkt_pts = AV_NOPTS_VALUE; ret = avcodec_decode_video2(ist->st->codec, decoded_frame, &got_output, &avpkt); quality = same_quant ? decoded_frame->quality : 0; if (ret < 0) goto fail; if (!got_output) { /* no picture yet */ av_freep(&decoded_frame); goto discard_packet; } ist->next_pts = ist->pts = guess_correct_pts(&ist->pts_ctx, decoded_frame->pkt_pts, decoded_frame->pkt_dts); if (ist->st->codec->time_base.num != 0) { int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame; ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec->time_base.num * ticks) / ist->st->codec->time_base.den; } avpkt.size = 0; buffer_to_free = NULL; pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free); break; case AVMEDIA_TYPE_SUBTITLE: ret = avcodec_decode_subtitle2(ist->st->codec, &subtitle, &got_output, &avpkt); if (ret < 0) return ret; if (!got_output) { goto discard_packet; } subtitle_to_free = &subtitle; avpkt.size = 0; break; default: return -1; } } else { switch(ist->st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) / ist->st->codec->sample_rate; break; case AVMEDIA_TYPE_VIDEO: if (ist->st->codec->time_base.num != 0) { int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame; ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec->time_base.num * ticks) / ist->st->codec->time_base.den; } break; } avpkt.size = 0; } // preprocess audio (volume) if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { if (audio_volume != 256) { switch (ist->st->codec->sample_fmt) { case AV_SAMPLE_FMT_U8: { uint8_t *volp = samples; for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) { int v = (((*volp - 128) * audio_volume + 128) >> 8) + 128; *volp++ = av_clip_uint8(v); } break; } case AV_SAMPLE_FMT_S16: { short *volp; volp = samples; for(i=0;i<(decoded_data_size / sizeof(short));i++) { int v = ((*volp) * audio_volume + 128) >> 8; *volp++ = av_clip_int16(v); } break; } case AV_SAMPLE_FMT_S32: { int32_t *volp = samples; for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) { int64_t v = (((int64_t)*volp * audio_volume + 128) >> 8); *volp++ = av_clipl_int32(v); } break; } case AV_SAMPLE_FMT_FLT: { float *volp = samples; float scale = audio_volume / 256.f; for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) { *volp++ *= scale; } break; } case AV_SAMPLE_FMT_DBL: { double *volp = samples; double scale = audio_volume / 256.; for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) { *volp++ *= scale; } break; } default: av_log(NULL, AV_LOG_FATAL, "Audio volume adjustment on sample format %s is not supported.\n", av_get_sample_fmt_name(ist->st->codec->sample_fmt)); exit_program(1); } } } /* frame rate emulation */ if (input_files[ist->file_index].rate_emu) { int64_t pts = av_rescale(ist->pts, 1000000, AV_TIME_BASE); int64_t now = av_gettime() - ist->start; if (pts > now) usleep(pts - now); } /* if output time reached then transcode raw format, encode packets and output them */ for (i = 0; i < nb_ostreams; i++) { OutputFile *of = &output_files[ost_table[i].file_index]; int frame_size; ost = &ost_table[i]; if (ost->source_index != ist_index) continue; if (of->start_time && ist->pts < of->start_time) continue; if (of->recording_time != INT64_MAX && av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + of->start_time, (AVRational){1, 1000000}) >= 0) { ost->is_past_recording_time = 1; continue; } #if CONFIG_AVFILTER if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->input_video_filter) { AVRational sar; if (ist->st->sample_aspect_ratio.num) sar = ist->st->sample_aspect_ratio; else sar = ist->st->codec->sample_aspect_ratio; av_vsrc_buffer_add_frame(ost->input_video_filter, decoded_frame, ist->pts, sar); if (!(filtered_frame = avcodec_alloc_frame())) { ret = AVERROR(ENOMEM); goto fail; } } frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || !ost->output_video_filter || avfilter_poll_frame(ost->output_video_filter->inputs[0]); while (frame_available) { AVRational ist_pts_tb; if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->output_video_filter) get_filtered_video_frame(ost->output_video_filter, filtered_frame, &ost->picref, &ist_pts_tb); if (ost->picref) ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q); #else filtered_frame = decoded_frame; #endif os = output_files[ost->file_index].ctx; /* set the input output pts pairs */ //ost->sync_ipts = (double)(ist->pts + input_files[ist->file_index].ts_offset - start_time)/ AV_TIME_BASE; if (ost->encoding_needed) { av_assert0(ist->decoding_needed); switch(ost->st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: do_audio_out(os, ost, ist, decoded_data_buf, decoded_data_size); break; case AVMEDIA_TYPE_VIDEO: #if CONFIG_AVFILTER if (ost->picref->video && !ost->frame_aspect_ratio) ost->st->codec->sample_aspect_ratio = ost->picref->video->pixel_aspect; #endif do_video_out(os, ost, ist, filtered_frame, &frame_size, same_quant ? quality : ost->st->codec->global_quality); if (vstats_filename && frame_size) do_video_stats(os, ost, frame_size); break; case AVMEDIA_TYPE_SUBTITLE: do_subtitle_out(os, ost, ist, &subtitle, pkt->pts); break; default: abort(); } } else { AVPacket opkt; int64_t ost_tb_start_time= av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base); av_init_packet(&opkt); if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && !copy_initial_nonkeyframes) #if !CONFIG_AVFILTER continue; #else goto cont; #endif /* no reencoding needed : output the packet directly */ /* force the input stream PTS */ if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) audio_size += data_size; else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { video_size += data_size; ost->sync_opts++; } opkt.stream_index= ost->index; if(pkt->pts != AV_NOPTS_VALUE) opkt.pts= av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time; else opkt.pts= AV_NOPTS_VALUE; if (pkt->dts == AV_NOPTS_VALUE) opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base); else opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base); opkt.dts -= ost_tb_start_time; opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base); opkt.flags= pkt->flags; //FIXME remove the following 2 lines they shall be replaced by the bitstream filters if( ost->st->codec->codec_id != CODEC_ID_H264 && ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO && ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO ) { if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & AV_PKT_FLAG_KEY)) opkt.destruct= av_destruct_packet; } else { opkt.data = data_buf; opkt.size = data_size; } write_frame(os, &opkt, ost->st->codec, ost->bitstream_filters); ost->st->codec->frame_number++; ost->frame_number++; av_free_packet(&opkt); } #if CONFIG_AVFILTER cont: frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) && ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]); if (ost->picref) avfilter_unref_buffer(ost->picref); } av_freep(&filtered_frame); #endif } fail: av_free(buffer_to_free); /* XXX: allocate the subtitles in the codec ? */ if (subtitle_to_free) { avsubtitle_free(subtitle_to_free); subtitle_to_free = NULL; } av_freep(&decoded_frame); if (ret < 0) return ret; } discard_packet: return 0; }