-
- /* get a handle to the output buffer */
- *ret = get_output_buffer (ffmpegdec, outbuf);
- if (G_UNLIKELY (*ret != GST_FLOW_OK))
- goto no_output;
-
- /*
- * Timestamps:
- *
- * 1) Copy picture timestamp if valid
- * 2) else interpolate from previous output timestamp
- * 3) else copy input timestamp
- */
- out_timestamp = -1;
- if (out_pts != -1) {
- /* Get (interpolated) timestamp from FFMPEG */
- out_timestamp = (GstClockTime) out_pts;
- GST_LOG_OBJECT (ffmpegdec, "using timestamp %" GST_TIME_FORMAT
- " returned by ffmpeg", GST_TIME_ARGS (out_timestamp));
- }
- if (!GST_CLOCK_TIME_IS_VALID (out_timestamp) && ffmpegdec->next_out != -1) {
- out_timestamp = ffmpegdec->next_out;
- GST_LOG_OBJECT (ffmpegdec, "using next timestamp %" GST_TIME_FORMAT,
- GST_TIME_ARGS (out_timestamp));
- }
- if (!GST_CLOCK_TIME_IS_VALID (out_timestamp)) {
- out_timestamp = dec_info->timestamp;
- GST_LOG_OBJECT (ffmpegdec, "using in timestamp %" GST_TIME_FORMAT,
- GST_TIME_ARGS (out_timestamp));
- }
- GST_BUFFER_TIMESTAMP (*outbuf) = out_timestamp;
-
- /*
- * Offset:
- * 0) Use stored input offset (from opaque)
- * 1) Use value converted from timestamp if valid
- * 2) Use input offset if valid
- */
- if (out_offset != GST_BUFFER_OFFSET_NONE) {
- /* out_offset already contains the offset from ts_info */
- GST_LOG_OBJECT (ffmpegdec, "Using offset returned by ffmpeg");
- } else if (out_timestamp != GST_CLOCK_TIME_NONE) {
- GstFormat out_fmt = GST_FORMAT_DEFAULT;
- GST_LOG_OBJECT (ffmpegdec, "Using offset converted from timestamp");
- /* FIXME, we should really remove this as it's not nice at all to do
- * upstream queries for each frame to get the frame offset. We also can't
- * really remove this because it is the only way of setting frame offsets
- * on outgoing buffers. We should have metadata so that the upstream peer
- * can set a frame number on the encoded data. */
- gst_pad_query_peer_convert (ffmpegdec->sinkpad,
- GST_FORMAT_TIME, out_timestamp, &out_fmt, &out_offset);
- } else if (dec_info->offset != GST_BUFFER_OFFSET_NONE) {
- /* FIXME, the input offset is input media specific and might not
- * be the same for the output media. (byte offset as input, frame number
- * as output, for example) */
- GST_LOG_OBJECT (ffmpegdec, "using in_offset %" G_GINT64_FORMAT,
- dec_info->offset);
- out_offset = dec_info->offset;
- } else {
- GST_LOG_OBJECT (ffmpegdec, "no valid offset found");
- out_offset = GST_BUFFER_OFFSET_NONE;
- }
- GST_BUFFER_OFFSET (*outbuf) = out_offset;
-
- /*
- * Duration:
- *
- * 1) Use reordered input duration if valid
- * 2) Else use input duration
- * 3) else use input framerate
- * 4) else use ffmpeg framerate
- */
- if (GST_CLOCK_TIME_IS_VALID (out_duration)) {
- /* We have a valid (reordered) duration */
- GST_LOG_OBJECT (ffmpegdec, "Using duration returned by ffmpeg");
- } else if (GST_CLOCK_TIME_IS_VALID (dec_info->duration)) {
- GST_LOG_OBJECT (ffmpegdec, "using in_duration");
- out_duration = dec_info->duration;
- } else if (GST_CLOCK_TIME_IS_VALID (ffmpegdec->last_diff)) {
- GST_LOG_OBJECT (ffmpegdec, "using last-diff");
- out_duration = ffmpegdec->last_diff;
- } else {
- /* if we have an input framerate, use that */
- if (ffmpegdec->format.video.fps_n != -1 &&
- (ffmpegdec->format.video.fps_n != 1000 &&
- ffmpegdec->format.video.fps_d != 1)) {
- GST_LOG_OBJECT (ffmpegdec, "using input framerate for duration");
- out_duration = gst_util_uint64_scale_int (GST_SECOND,
- ffmpegdec->format.video.fps_d, ffmpegdec->format.video.fps_n);
- } else {
- /* don't try to use the decoder's framerate when it seems a bit abnormal,
- * which we assume when den >= 1000... */
- if (ffmpegdec->context->time_base.num != 0 &&
- (ffmpegdec->context->time_base.den > 0 &&
- ffmpegdec->context->time_base.den < 1000)) {
- GST_LOG_OBJECT (ffmpegdec, "using decoder's framerate for duration");
- out_duration = gst_util_uint64_scale_int (GST_SECOND,
- ffmpegdec->context->time_base.num *
- ffmpegdec->context->ticks_per_frame,
- ffmpegdec->context->time_base.den);
- } else {
- GST_LOG_OBJECT (ffmpegdec, "no valid duration found");
- }
- }
- }
-
- /* Take repeat_pict into account */
- if (GST_CLOCK_TIME_IS_VALID (out_duration)) {
- out_duration += out_duration * ffmpegdec->picture->repeat_pict / 2;
- }
- GST_BUFFER_DURATION (*outbuf) = out_duration;
-
- if (out_timestamp != -1 && out_duration != -1 && out_duration != 0)
- ffmpegdec->next_out = out_timestamp + out_duration;
- else
- ffmpegdec->next_out = -1;