static GstVaapiDecoderStatus gst_vaapi_decoder_vp8_end_frame (GstVaapiDecoder * base_decoder) { GstVaapiDecoderVp8 *const decoder = GST_VAAPI_DECODER_VP8_CAST (base_decoder); return decode_current_picture (decoder); }
static GstVaapiDecoderStatus gst_vaapi_decoder_jpeg_end_frame (GstVaapiDecoder * base_decoder) { GstVaapiDecoderJpeg *const decoder = GST_VAAPI_DECODER_JPEG_CAST (base_decoder); return decode_current_picture (decoder); }
static GstVaapiDecoderStatus decode_picture( GstVaapiDecoderJpeg *decoder, guint8 profile, guchar *buf, guint buf_size, GstClockTime pts ) { GstVaapiDecoderJpegPrivate * const priv = decoder->priv; GstJpegFrameHdr * const frame_hdr = &priv->frame_hdr; GstVaapiPicture *picture; GstVaapiDecoderStatus status; switch (profile) { case GST_JPEG_MARKER_SOF_MIN: priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE; break; default: GST_ERROR("unsupported profile %d", profile); return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE; } memset(frame_hdr, 0, sizeof(*frame_hdr)); if (!gst_jpeg_parse_frame_hdr(frame_hdr, buf, buf_size, 0)) { GST_ERROR("failed to parse image"); return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER; } priv->height = frame_hdr->height; priv->width = frame_hdr->width; status = ensure_context(decoder); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) { GST_ERROR("failed to reset context"); return status; } if (priv->current_picture && !decode_current_picture(decoder)) return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; picture = GST_VAAPI_PICTURE_NEW(JPEGBaseline, decoder); if (!picture) { GST_ERROR("failed to allocate picture"); return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; } gst_vaapi_picture_replace(&priv->current_picture, picture); gst_vaapi_picture_unref(picture); if (!fill_picture(decoder, picture, frame_hdr)) return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; /* Update presentation time */ picture->pts = pts; return GST_VAAPI_DECODER_STATUS_SUCCESS; }
static GstVaapiDecoderStatus decode_sequence_end(GstVaapiDecoderVC1 *decoder) { GstVaapiDecoderVC1Private * const priv = decoder->priv; if (priv->current_picture && !decode_current_picture(decoder)) return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; gst_vaapi_dpb_flush(priv->dpb); return GST_VAAPI_DECODER_STATUS_END_OF_STREAM; }
static GstVaapiDecoderStatus decode_frame(GstVaapiDecoderVC1 *decoder, GstVC1BDU *rbdu, GstVC1BDU *ebdu) { GstVaapiDecoderVC1Private * const priv = decoder->priv; GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr; GstVC1AdvancedSeqHdr *advanced = &seq_hdr->advanced; GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr; GstVC1ParserResult result; GstVaapiPicture *picture; GstVaapiSlice *slice; GstVaapiDecoderStatus status; VASliceParameterBufferVC1 *slice_param; GstClockTime pts; gint32 poc; status = ensure_context(decoder); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) { GST_DEBUG("failed to reset context"); return status; } if (priv->current_picture ) { if(!decode_current_picture(decoder)) return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; } picture = GST_VAAPI_PICTURE_NEW(VC1, decoder); if (!picture) { GST_DEBUG("failed to allocate picture"); return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; } if (!gst_vc1_bitplanes_ensure_size(priv->bitplanes, seq_hdr)) { GST_DEBUG("failed to allocate bitplanes"); return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; } memset(frame_hdr, 0, sizeof(*frame_hdr)); result = gst_vc1_parse_frame_header( rbdu->data + rbdu->offset, rbdu->size, frame_hdr, seq_hdr, priv->bitplanes ); if (result != GST_VC1_PARSER_OK) { GST_DEBUG("failed to parse frame layer"); return get_status(result); } switch (frame_hdr->ptype) { case GST_VC1_PICTURE_TYPE_I: picture->type = GST_VAAPI_PICTURE_TYPE_I; GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE); break; case GST_VC1_PICTURE_TYPE_SKIPPED: case GST_VC1_PICTURE_TYPE_P: picture->type = GST_VAAPI_PICTURE_TYPE_P; GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE); break; case GST_VC1_PICTURE_TYPE_B: picture->type = GST_VAAPI_PICTURE_TYPE_B; priv->successive_bfrm_cnt += 1; break; case GST_VC1_PICTURE_TYPE_BI: picture->type = GST_VAAPI_PICTURE_TYPE_BI; priv->successive_bfrm_cnt += 1; break; default: GST_DEBUG("unsupported picture type %d", frame_hdr->ptype); return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; } /*As far as dpb is only storing the reference pictures, always increesing poc should work fine. But we should explictly calculate the pts of frames*/ if(!GST_VAAPI_PICTURE_IS_REFERENCE(picture)) picture->poc = priv->frm_cnt - 1; else picture->poc = priv->frm_cnt; gst_vaapi_decoder_get_framerate(GST_VAAPI_DECODER_CAST(decoder), &priv->fps_n, &priv->fps_d); pts = gst_util_uint64_scale(picture->poc, GST_SECOND * priv->fps_d, priv->fps_n); if(GST_VAAPI_PICTURE_IS_REFERENCE(picture)){ if (priv->successive_bfrm_cnt) { poc = priv->frm_cnt - priv->successive_bfrm_cnt - 1; pts = gst_util_uint64_scale(picture->poc, GST_SECOND * priv->fps_d, priv->fps_n); gst_vaapi_dpb_reset_pts (priv->dpb, poc, pts); priv->successive_bfrm_cnt = 0; } } picture->pts = pts; priv->frm_cnt++; if (!fill_picture(decoder, picture)) return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; slice = GST_VAAPI_SLICE_NEW( VC1, decoder, ebdu->data + ebdu->sc_offset, ebdu->size + ebdu->offset - ebdu->sc_offset ); if (!slice) { GST_DEBUG("failed to allocate slice"); return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; } gst_vaapi_picture_add_slice(picture, slice); /* Fill in VASliceParameterBufferVC1 */ slice_param = slice->param; slice_param->macroblock_offset = 8 * (ebdu->offset - ebdu->sc_offset) + frame_hdr->header_size; slice_param->slice_vertical_position = 0; gst_vaapi_picture_replace(&priv->current_picture, picture); gst_vaapi_picture_unref(picture); return GST_VAAPI_DECODER_STATUS_SUCCESS; }
static GstVaapiDecoderStatus decode_buffer(GstVaapiDecoderJpeg *decoder, GstBuffer *buffer) { GstVaapiDecoderJpegPrivate * const priv = decoder->priv; GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; GstJpegMarkerSegment seg; GstJpegScanSegment scan_seg; GstClockTime pts; guchar *buf; guint buf_size, ofs; gboolean append_ecs; buf = GST_BUFFER_DATA(buffer); buf_size = GST_BUFFER_SIZE(buffer); if (!buf && buf_size == 0) return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; memset(&scan_seg, 0, sizeof(scan_seg)); pts = GST_BUFFER_TIMESTAMP(buffer); ofs = 0; while (gst_jpeg_parse(&seg, buf, buf_size, ofs)) { if (seg.size < 0) { GST_DEBUG("buffer to short for parsing"); return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; } ofs += seg.size; /* Decode scan, if complete */ if (seg.marker == GST_JPEG_MARKER_EOI && scan_seg.header_size > 0) { scan_seg.data_size = seg.offset - scan_seg.data_offset; scan_seg.is_valid = TRUE; } if (scan_seg.is_valid) { status = decode_scan( decoder, buf + scan_seg.header_offset, scan_seg.header_size, buf + scan_seg.data_offset, scan_seg.data_size ); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) break; memset(&scan_seg, 0, sizeof(scan_seg)); } append_ecs = TRUE; switch (seg.marker) { case GST_JPEG_MARKER_SOI: priv->has_quant_table = FALSE; priv->has_huf_table = FALSE; priv->mcu_restart = 0; status = GST_VAAPI_DECODER_STATUS_SUCCESS; break; case GST_JPEG_MARKER_EOI: if (decode_current_picture(decoder)) { /* Get out of the loop, trailing data is not needed */ status = GST_VAAPI_DECODER_STATUS_SUCCESS; goto end; } status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; break; case GST_JPEG_MARKER_DHT: status = decode_huffman_table(decoder, buf + seg.offset, seg.size); break; case GST_JPEG_MARKER_DQT: status = decode_quant_table(decoder, buf + seg.offset, seg.size); break; case GST_JPEG_MARKER_DRI: status = decode_restart_interval(decoder, buf + seg.offset, seg.size); break; case GST_JPEG_MARKER_DAC: GST_ERROR("unsupported arithmetic coding mode"); status = GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE; break; case GST_JPEG_MARKER_SOS: scan_seg.header_offset = seg.offset; scan_seg.header_size = seg.size; scan_seg.data_offset = seg.offset + seg.size; scan_seg.data_size = 0; append_ecs = FALSE; break; default: /* Restart marker */ if (seg.marker >= GST_JPEG_MARKER_RST_MIN && seg.marker <= GST_JPEG_MARKER_RST_MAX) { append_ecs = FALSE; break; } /* Frame header */ if (seg.marker >= GST_JPEG_MARKER_SOF_MIN && seg.marker <= GST_JPEG_MARKER_SOF_MAX) { status = decode_picture( decoder, seg.marker, buf + seg.offset, seg.size, pts ); break; } /* Application segments */ if (seg.marker >= GST_JPEG_MARKER_APP_MIN && seg.marker <= GST_JPEG_MARKER_APP_MAX) { status = GST_VAAPI_DECODER_STATUS_SUCCESS; break; } GST_WARNING("unsupported marker (0x%02x)", seg.marker); status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER; break; } /* Append entropy coded segments */ if (append_ecs) scan_seg.data_size = seg.offset - scan_seg.data_offset; if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) break; } end: return status; }