LIBDE265_API const struct de265_image* de265_get_next_picture(de265_decoder_context* de265ctx) { const struct de265_image* img = de265_peek_next_picture(de265ctx); if (img) { de265_release_next_picture(de265ctx); } return img; }
static GstFlowReturn gst_libde265_dec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame) { GstLibde265Dec *dec = GST_LIBDE265_DEC (decoder); uint8_t *frame_data; uint8_t *end_data; const struct de265_image *img; de265_error ret = DE265_OK; int more = 0; GstClockTime pts; gsize size; GstMapInfo info; pts = frame->pts; if (pts == GST_CLOCK_TIME_NONE) { pts = frame->dts; } if (!gst_buffer_map (frame->input_buffer, &info, GST_MAP_READ)) { GST_ERROR_OBJECT (dec, "Failed to map input buffer"); return GST_FLOW_ERROR; } frame_data = info.data; size = info.size; end_data = frame_data + size; if (size > 0) { if (dec->format == GST_TYPE_LIBDE265_FORMAT_PACKETIZED) { /* stream contains length fields and NALs */ uint8_t *start_data = frame_data; while (start_data + dec->length_size <= end_data) { int nal_size = 0; int i; for (i = 0; i < dec->length_size; i++) { nal_size = (nal_size << 8) | start_data[i]; } if (start_data + dec->length_size + nal_size > end_data) { GST_ELEMENT_ERROR (decoder, STREAM, DECODE, ("Overflow in input data, check stream format"), (NULL)); goto error_input; } ret = de265_push_NAL (dec->ctx, start_data + dec->length_size, nal_size, (de265_PTS) pts, (void *) (uintptr_t) (frame->system_frame_number + 1)); if (ret != DE265_OK) { GST_ELEMENT_ERROR (decoder, STREAM, DECODE, ("Error while pushing data: %s (code=%d)", de265_get_error_text (ret), ret), (NULL)); goto error_input; } start_data += dec->length_size + nal_size; } } else { ret = de265_push_data (dec->ctx, frame_data, size, (de265_PTS) pts, (void *) (uintptr_t) (frame->system_frame_number + 1)); if (ret != DE265_OK) { GST_ELEMENT_ERROR (decoder, STREAM, DECODE, ("Error while pushing data: %s (code=%d)", de265_get_error_text (ret), ret), (NULL)); goto error_input; } } } else { ret = de265_flush_data (dec->ctx); if (ret != DE265_OK) { GST_ELEMENT_ERROR (decoder, STREAM, DECODE, ("Error while flushing data: %s (code=%d)", de265_get_error_text (ret), ret), (NULL)); goto error_input; } } gst_buffer_unmap (frame->input_buffer, &info); /* decode as much as possible */ do { ret = de265_decode (dec->ctx, &more); } while (more && ret == DE265_OK); switch (ret) { case DE265_OK: case DE265_ERROR_WAITING_FOR_INPUT_DATA: break; case DE265_ERROR_IMAGE_BUFFER_FULL: dec->buffer_full = 1; if ((img = de265_peek_next_picture (dec->ctx)) == NULL) { return GST_FLOW_OK; } break; default: GST_ELEMENT_ERROR (decoder, STREAM, DECODE, ("Error while decoding: %s (code=%d)", de265_get_error_text (ret), ret), (NULL)); return GST_FLOW_ERROR; } while ((ret = de265_get_warning (dec->ctx)) != DE265_OK) { GST_ELEMENT_WARNING (decoder, STREAM, DECODE, ("%s (code=%d)", de265_get_error_text (ret), ret), (NULL)); } img = de265_get_next_picture (dec->ctx); if (img == NULL) { /* need more data */ return GST_FLOW_OK; } return _gst_libde265_return_image (decoder, frame, img); error_input: gst_buffer_unmap (frame->input_buffer, &info); return GST_FLOW_ERROR; }
static GstFlowReturn gst_libde265_dec_parse_data (VIDEO_DECODER_BASE * parse, gboolean at_eos) #endif { GstLibde265Dec *dec = GST_LIBDE265_DEC (parse); const struct de265_image *img; de265_error ret = DE265_OK; int more = 0; #if GST_CHECK_VERSION(1,0,0) de265_PTS pts = (de265_PTS) frame->pts; #else de265_PTS pts = 0; #endif if (dec->buffer_full) { // return any pending images before decoding more data if ((img = de265_peek_next_picture(dec->ctx)) != NULL) { return _gst_libde265_image_available(parse, img); } dec->buffer_full = 0; } #if !GST_CHECK_VERSION(1,0,0) GstAdapter *adapter = parse->input_adapter; #endif gsize size = gst_adapter_available (adapter); if (size == 0) { return NEED_DATA_RESULT; } GstBuffer *buf = gst_adapter_take_buffer(adapter, size); uint8_t *frame_data; uint8_t *end_data; #if GST_CHECK_VERSION(1,0,0) GstMapInfo info; if (!gst_buffer_map(buf, &info, GST_MAP_READWRITE)) { return GST_FLOW_ERROR; } frame_data = info.data; #else frame_data = GST_BUFFER_DATA(buf); #endif end_data = frame_data + size; if (size > 0) { if (dec->mode == GST_TYPE_LIBDE265_DEC_PACKETIZED) { // replace 4-byte length fields with NAL start codes uint8_t *start_data = frame_data; while (start_data + 4 <= end_data) { int nal_size = READ_BE32(start_data); if (start_data + nal_size > end_data) { GST_ELEMENT_ERROR (parse, STREAM, DECODE, ("Overflow in input data, check data mode"), (NULL)); goto error; } ret = de265_push_NAL(dec->ctx, start_data + 4, nal_size, pts, NULL); if (ret != DE265_OK) { GST_ELEMENT_ERROR (parse, STREAM, DECODE, ("Error while pushing data: %s (code=%d)", de265_get_error_text(ret), ret), (NULL)); goto error; } start_data += 4 + nal_size; } } else { ret = de265_push_data(dec->ctx, frame_data, size, pts, NULL); } } else { ret = de265_flush_data(dec->ctx); } // decode as much as possible do { ret = de265_decode(dec->ctx, &more); } while (more && ret == DE265_OK); #if GST_CHECK_VERSION(1,0,0) gst_buffer_unmap(buf, &info); #endif gst_buffer_unref(buf); switch (ret) { case DE265_OK: break; case DE265_ERROR_IMAGE_BUFFER_FULL: dec->buffer_full = 1; if ((img = de265_peek_next_picture(dec->ctx)) == NULL) { return NEED_DATA_RESULT; } return _gst_libde265_image_available(parse, img);; case DE265_ERROR_WAITING_FOR_INPUT_DATA: return NEED_DATA_RESULT; default: GST_ELEMENT_ERROR (parse, STREAM, DECODE, ("Error while decoding: %s (code=%d)", de265_get_error_text(ret), ret), (NULL)); return GST_FLOW_ERROR; } while ((ret = de265_get_warning(dec->ctx)) != DE265_OK) { GST_ELEMENT_WARNING (parse, STREAM, DECODE, ("%s (code=%d)", de265_get_error_text(ret), ret), (NULL)); } if ((img = de265_peek_next_picture(dec->ctx)) == NULL) { // need more data return NEED_DATA_RESULT; } return _gst_libde265_image_available(parse, img); error: #if GST_CHECK_VERSION(1,0,0) gst_buffer_unmap(buf, &info); #endif gst_buffer_unref(buf); return GST_FLOW_ERROR; }