static GstFlowReturn gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf) { GstKateTiger *tiger = GST_KATE_TIGER (gst_pad_get_parent (pad)); GstFlowReturn rflow = GST_FLOW_OK; unsigned char *ptr; int ret; g_mutex_lock (tiger->mutex); GST_LOG_OBJECT (tiger, "got video frame, %u bytes", GST_BUFFER_SIZE (buf)); /* draw on it */ buf = gst_buffer_make_writable (buf); if (G_UNLIKELY (!buf)) { GST_WARNING_OBJECT (tiger, "Failed to make video buffer writable"); } else { ptr = GST_BUFFER_DATA (buf); if (!ptr) { GST_WARNING_OBJECT (tiger, "Failed to get a pointer to video buffer data"); } else { ret = tiger_renderer_set_buffer (tiger->tr, ptr, tiger->video_width, tiger->video_height, tiger->video_width * 4, 0); // TODO: stride ? if (G_UNLIKELY (ret < 0)) { GST_WARNING_OBJECT (tiger, "Tiger renderer failed to set buffer to video frame: %d", ret); } else { kate_float t = GST_BUFFER_TIMESTAMP (buf) / (gdouble) GST_SECOND; ret = tiger_renderer_update (tiger->tr, t, 1); if (G_UNLIKELY (ret < 0)) { GST_WARNING_OBJECT (tiger, "Tiger renderer failed to update: %d", ret); } else { ret = tiger_renderer_render (tiger->tr); if (G_UNLIKELY (ret < 0)) { GST_WARNING_OBJECT (tiger, "Tiger renderer failed to render to video frame: %d", ret); } else { GST_LOG_OBJECT (tiger, "Tiger renderer rendered on video frame at %f", t); } } } } } rflow = gst_pad_push (tiger->srcpad, buf); gst_object_unref (tiger); g_mutex_unlock (tiger->mutex); return rflow; }
OggPlayErrorCode oggplay_data_update_tiger(OggPlayKateDecode *decode, int active, ogg_int64_t presentation_time, OggPlayCallbackInfo *info) { OggPlayOverlayRecord * record = NULL; OggPlayOverlayData * data = NULL; size_t size = sizeof (OggPlayOverlayRecord); int track = active && decode->use_tiger; int ret; kate_float t = OGGPLAY_TIME_FP_TO_INT(presentation_time) / 1000.0f; if (!decode->decoder.initialised) return -1; if (track) { if (info) { if (info->required_records>0) { OggPlayDataHeader *header = info->records[0]; data = (OggPlayOverlayData*)(header+1); if (decode->tr && data->rgb) { #if WORDS_BIGENDIAN || IS_BIG_ENDIAN tiger_renderer_set_buffer(decode->tr, data->rgb, data->width, data->height, data->stride, 0); #else tiger_renderer_set_buffer(decode->tr, data->rgb, data->width, data->height, data->stride, 1); #endif } else { /* we're supposed to overlay on a frame, but the available frame has no RGB buffer */ /* fprintf(stderr,"no RGB buffer found for video frame\n"); */ return -1; } } else { /* we're supposed to overlay on a frame, but there is no frame available */ /* fprintf(stderr,"no video frame to overlay on\n"); */ return -1; } } else { // TODO: some way of knowing the size of the video we'll be drawing onto, if any int width = decode->k_state.ki->original_canvas_width; int height = decode->k_state.ki->original_canvas_height; long overlay_size; if (width <= 0 || height <= 0) { /* some default resolution if we're not overlaying onto a video and the canvas size is unknown */ if (decode->default_width > 0 && decode->default_height > 0) { width = decode->default_width; height = decode->default_height; } else { width = 640; height = 480; } } /* check for integer overflow */ ret = oggplay_mul_signed_overflow (width, height, &overlay_size); if (ret == E_OGGPLAY_TYPE_OVERFLOW) { return ret; } ret = oggplay_mul_signed_overflow (overlay_size, 4, &overlay_size); if (ret == E_OGGPLAY_TYPE_OVERFLOW) { return E_OGGPLAY_TYPE_OVERFLOW; } ret = oggplay_check_add_overflow (size, overlay_size, &size); if (ret == E_OGGPLAY_TYPE_OVERFLOW) { return E_OGGPLAY_TYPE_OVERFLOW; } record = (OggPlayOverlayRecord*)oggplay_calloc (1, size); if (!record) return E_OGGPLAY_OUT_OF_MEMORY; record->header.samples_in_record = 1; data= &(record->data); oggplay_data_initialise_header((OggPlayDecode *)decode, &(record->header)); data->rgba = (unsigned char*)(record+1); data->rgb = NULL; data->width = width; data->height = height; data->stride = width*4; if (decode->tr && data->rgba) { tiger_renderer_set_buffer(decode->tr, data->rgba, data->width, data->height, data->stride, decode->swap_rgb); } oggplay_data_add_to_list(&decode->decoder, &(record->header)); record->header.presentation_time=presentation_time; } } if (decode->tr) { tiger_renderer_update(decode->tr, t, track); } if (track) { /* buffer was either calloced, so already cleared, or already filled with video, so no clearing */ if (decode->tr) { tiger_renderer_render(decode->tr); } } return E_OGGPLAY_CONTINUE; }