static GstFlowReturn gst_mpeg2dec_alloc_buffer (GstMpeg2dec * mpeg2dec, GstVideoCodecFrame * frame, GstBuffer ** buffer) { GstFlowReturn ret; GstVideoFrame vframe; guint8 *buf[3]; ret = gst_mpeg2dec_alloc_sized_buf (mpeg2dec, mpeg2dec->decoded_info.size, frame, buffer); if (G_UNLIKELY (ret != GST_FLOW_OK)) goto beach; if (mpeg2dec->need_cropping && mpeg2dec->has_cropping) { GstVideoCropMeta *crop; GstVideoCodecState *state; GstVideoInfo *vinfo; state = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (mpeg2dec)); vinfo = &state->info; crop = gst_buffer_add_video_crop_meta (frame->output_buffer); /* we can do things slightly more efficient when we know that * downstream understands clipping */ crop->x = 0; crop->y = 0; crop->width = vinfo->width; crop->height = vinfo->height; gst_video_codec_state_unref (state); } if (!gst_video_frame_map (&vframe, &mpeg2dec->decoded_info, *buffer, GST_MAP_READ | GST_MAP_WRITE)) goto map_fail; buf[0] = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0); buf[1] = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 1); buf[2] = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 2); GST_DEBUG_OBJECT (mpeg2dec, "set_buf: %p %p %p, frame %i", buf[0], buf[1], buf[2], frame->system_frame_number); /* Note: We use a non-null 'id' value to make the distinction * between the dummy buffers (which have an id of NULL) and the * ones we did */ mpeg2_set_buf (mpeg2dec->decoder, buf, GINT_TO_POINTER (frame->system_frame_number + 1)); gst_mpeg2dec_save_buffer (mpeg2dec, frame->system_frame_number, &vframe); beach: return ret; map_fail: { GST_ERROR_OBJECT (mpeg2dec, "Failed to map frame"); return GST_FLOW_ERROR; } }
static GstFlowReturn handle_picture (GstMpeg2dec * mpeg2dec, const mpeg2_info_t * info, GstVideoCodecFrame * frame) { GstVideoDecoder *decoder = (GstVideoDecoder *) mpeg2dec; GstFlowReturn ret; gint type; const gchar *type_str = NULL; gboolean key_frame = FALSE; const mpeg2_picture_t *picture = info->current_picture; GstVideoFrame vframe; guint8 *buf[3]; ret = gst_video_decoder_allocate_output_frame (decoder, frame); if (ret != GST_FLOW_OK) return ret; type = picture->flags & PIC_MASK_CODING_TYPE; switch (type) { case PIC_FLAG_CODING_TYPE_I: key_frame = TRUE; mpeg2_skip (mpeg2dec->decoder, 0); type_str = "I"; break; case PIC_FLAG_CODING_TYPE_P: type_str = "P"; break; case PIC_FLAG_CODING_TYPE_B: type_str = "B"; break; default: gst_video_codec_frame_ref (frame); ret = gst_video_decoder_drop_frame (GST_VIDEO_DECODER (mpeg2dec), frame); GST_VIDEO_DECODER_ERROR (mpeg2dec, 1, STREAM, DECODE, ("decoding error"), ("Invalid picture type"), ret); return ret; } GST_DEBUG_OBJECT (mpeg2dec, "handle picture type %s", type_str); GST_DEBUG_OBJECT (mpeg2dec, "picture %s, frame %i", key_frame ? ", kf," : " ", frame->system_frame_number); if (GST_VIDEO_INFO_IS_INTERLACED (&mpeg2dec->decoded_info)) { /* This implies SEQ_FLAG_PROGRESSIVE_SEQUENCE is not set */ if (picture->flags & PIC_FLAG_TOP_FIELD_FIRST) { GST_BUFFER_FLAG_SET (frame->output_buffer, GST_VIDEO_BUFFER_FLAG_TFF); } if (!(picture->flags & PIC_FLAG_PROGRESSIVE_FRAME)) { GST_BUFFER_FLAG_SET (frame->output_buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED); } #if MPEG2_RELEASE >= MPEG2_VERSION(0,5,0) /* repeat field introduced in 0.5.0 */ if (picture->flags & PIC_FLAG_REPEAT_FIRST_FIELD) { GST_BUFFER_FLAG_SET (frame->output_buffer, GST_VIDEO_BUFFER_FLAG_RFF); } #endif } if (mpeg2dec->discont_state == MPEG2DEC_DISC_NEW_PICTURE && key_frame) { mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_KEYFRAME; } GST_DEBUG_OBJECT (mpeg2dec, "picture: %s %s %s %s %s fields:%d ts:%" GST_TIME_FORMAT, (picture->flags & PIC_FLAG_PROGRESSIVE_FRAME ? "prog" : " "), (picture->flags & PIC_FLAG_TOP_FIELD_FIRST ? "tff" : " "), #if MPEG2_RELEASE >= MPEG2_VERSION(0,5,0) (picture->flags & PIC_FLAG_REPEAT_FIRST_FIELD ? "rff" : " "), #else "unknown rff", #endif (picture->flags & PIC_FLAG_SKIP ? "skip" : " "), (picture->flags & PIC_FLAG_COMPOSITE_DISPLAY ? "composite" : " "), picture->nb_fields, GST_TIME_ARGS (frame->pts)); if (!gst_video_frame_map (&vframe, &mpeg2dec->decoded_info, frame->output_buffer, GST_MAP_READ | GST_MAP_WRITE)) goto map_fail; buf[0] = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0); buf[1] = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 1); buf[2] = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 2); GST_DEBUG_OBJECT (mpeg2dec, "set_buf: %p %p %p, frame %i", buf[0], buf[1], buf[2], frame->system_frame_number); /* Note: We use a non-null 'id' value to make the distinction * between the dummy buffers (which have an id of NULL) and the * ones we did */ mpeg2_stride (mpeg2dec->decoder, vframe.info.stride[0]); mpeg2_set_buf (mpeg2dec->decoder, buf, GINT_TO_POINTER (frame->system_frame_number + 1)); gst_mpeg2dec_save_buffer (mpeg2dec, frame->system_frame_number, &vframe); return ret; map_fail: { GST_ELEMENT_ERROR (mpeg2dec, RESOURCE, WRITE, ("Failed to map frame"), (NULL)); return GST_FLOW_ERROR; } }