/* Schrodinger * Copyright (C) 2008 David Schleef * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "gstschroutils.h" //#define SCHRO_ENABLE_UNSTABLE_API #include #include #include #include #include #include #include GST_DEBUG_CATEGORY_EXTERN (schro_debug); #define GST_CAT_DEFAULT schro_debug typedef struct { GstVideoFrame frame; } FrameData; static void gst_schro_frame_free (SchroFrame * frame, void *priv) { FrameData *data = priv; gst_video_frame_unmap (&data->frame); g_slice_free (FrameData, data); } GstBuffer * gst_schro_frame_get_buffer (SchroFrame * frame) { if (frame->priv) return gst_buffer_ref (((FrameData *) frame->priv)->frame.buffer); return NULL; } SchroFrame * gst_schro_buffer_wrap (GstBuffer * buf, gboolean write, GstVideoInfo * vinfo) { SchroFrame *frame; GstVideoFrame vframe; FrameData *data; gint i; if (!gst_video_frame_map (&vframe, vinfo, buf, (write ? GST_MAP_READWRITE : GST_MAP_READ))) return NULL; frame = schro_frame_new (); frame->width = GST_VIDEO_FRAME_WIDTH (&vframe); frame->height = GST_VIDEO_FRAME_HEIGHT (&vframe); switch (GST_VIDEO_FRAME_FORMAT (&vframe)) { case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: frame->format = SCHRO_FRAME_FORMAT_U8_420; break; case GST_VIDEO_FORMAT_YUY2: frame->format = SCHRO_FRAME_FORMAT_YUYV; break; case GST_VIDEO_FORMAT_UYVY: frame->format = SCHRO_FRAME_FORMAT_UYVY; break; case GST_VIDEO_FORMAT_AYUV: frame->format = SCHRO_FRAME_FORMAT_AYUV; break; #if SCHRO_CHECK_VERSION(1,0,12) case GST_VIDEO_FORMAT_ARGB: frame->format = SCHRO_FRAME_FORMAT_ARGB; break; #endif #if SCHRO_CHECK_VERSION(1,0,11) case GST_VIDEO_FORMAT_Y42B: frame->format = SCHRO_FRAME_FORMAT_U8_422; break; case GST_VIDEO_FORMAT_Y444: frame->format = SCHRO_FRAME_FORMAT_U8_444; break; case GST_VIDEO_FORMAT_v210: frame->format = SCHRO_FRAME_FORMAT_v210; break; case GST_VIDEO_FORMAT_v216: frame->format = SCHRO_FRAME_FORMAT_v216; break; case GST_VIDEO_FORMAT_AYUV64: frame->format = SCHRO_FRAME_FORMAT_AY64; break; #endif default: g_assert_not_reached (); return NULL; } if (SCHRO_FRAME_IS_PACKED (frame->format)) { frame->components[0].format = frame->format; frame->components[0].width = frame->width; frame->components[0].height = frame->height; frame->components[0].stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 0); frame->components[0].length = frame->components[0].stride * frame->height; frame->components[0].data = vframe.data[0]; frame->components[0].v_shift = 0; frame->components[0].h_shift = 0; } else { for (i = 0; i < GST_VIDEO_FRAME_N_COMPONENTS (&vframe); i++) { frame->components[i].format = frame->format; frame->components[i].width = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, i); frame->components[i].height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i); frame->components[i].stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i); frame->components[i].length = frame->components[i].stride * frame->components[i].height; frame->components[i].data = GST_VIDEO_FRAME_COMP_DATA (&vframe, i); if (i == 0) { frame->components[i].v_shift = 0; frame->components[i].h_shift = 0; } else { frame->components[i].v_shift = SCHRO_FRAME_FORMAT_H_SHIFT (frame->format); frame->components[i].h_shift = SCHRO_FRAME_FORMAT_H_SHIFT (frame->format); } } } data = g_slice_new0 (FrameData); data->frame = vframe; schro_frame_set_free_callback (frame, gst_schro_frame_free, data); return frame; } static void schro_buf_free_func (gpointer priv) { SchroBuffer *buffer = (SchroBuffer *) priv; schro_buffer_unref (buffer); } /* takes the reference */ GstBuffer * gst_schro_wrap_schro_buffer (SchroBuffer * buffer) { GstMemory *mem; GstBuffer *buf; mem = gst_memory_new_wrapped (0, buffer->data, buffer->length, 0, buffer->length, buffer, schro_buf_free_func); buf = gst_buffer_new (); gst_buffer_append_memory (buf, mem); return buf; } typedef struct { GstMemory *mem; GstMapInfo info; } BufferData; static void gst_schro_buffer_free (SchroBuffer * buffer, void *priv) { BufferData *data = priv; gst_memory_unmap (data->mem, &data->info); gst_memory_unref (data->mem); g_slice_free (BufferData, priv); } SchroBuffer * gst_schro_wrap_gst_buffer (GstBuffer * buffer) { SchroBuffer *schrobuf; GstMemory *mem; GstMapInfo info; BufferData *data; mem = gst_buffer_get_all_memory (buffer); if (!gst_memory_map (mem, &info, GST_MAP_READ)) { GST_ERROR ("Couldn't get readable memory from gstbuffer"); return NULL; } /* FIXME : We can't control if data won't be read/write outside * of schro ... */ data = g_slice_new0 (BufferData); data->info = info; data->mem = mem; schrobuf = schro_buffer_new_with_data (info.data, info.size); schrobuf->free = gst_schro_buffer_free; schrobuf->priv = data; return schrobuf; }