[encoder] Added 1/8th pel MV refinement
[schroedinger/research-port.git] / gst / gstbasevideoutils.c
blobd728a3202d1e8ea848514ffd6f458b98b91e4487
1 /* GStreamer
2 * Copyright (C) 2008 David Schleef <ds@schleef.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <string.h>
26 #include "gstbasevideoutils.h"
29 guint64
30 gst_base_video_convert_bytes_to_frames (GstVideoState *state,
31 guint64 bytes)
33 return gst_util_uint64_scale_int (bytes, 1, state->bytes_per_picture);
36 guint64
37 gst_base_video_convert_frames_to_bytes (GstVideoState *state,
38 guint64 frames)
40 return frames * state->bytes_per_picture;
44 gboolean
45 gst_base_video_rawvideo_convert (GstVideoState *state,
46 GstFormat src_format, gint64 src_value,
47 GstFormat * dest_format, gint64 *dest_value)
49 gboolean res = FALSE;
51 if (src_format == *dest_format) {
52 *dest_value = src_value;
53 return TRUE;
56 if (src_format == GST_FORMAT_BYTES &&
57 *dest_format == GST_FORMAT_DEFAULT) {
58 /* convert bytes to frames */
59 *dest_value = gst_util_uint64_scale_int (src_value, 1,
60 state->bytes_per_picture);
61 res = TRUE;
62 } else if (src_format == GST_FORMAT_DEFAULT &&
63 *dest_format == GST_FORMAT_BYTES) {
64 /* convert bytes to frames */
65 *dest_value = src_value * state->bytes_per_picture;
66 res = TRUE;
67 } else if (src_format == GST_FORMAT_DEFAULT &&
68 *dest_format == GST_FORMAT_TIME) {
69 /* convert frames to time */
70 /* FIXME add segment time? */
71 *dest_value = gst_util_uint64_scale (src_value,
72 GST_SECOND * state->fps_d, state->fps_n);
73 res = TRUE;
74 } else if (src_format == GST_FORMAT_TIME &&
75 *dest_format == GST_FORMAT_DEFAULT) {
76 /* convert time to frames */
77 /* FIXME subtract segment time? */
78 *dest_value = gst_util_uint64_scale (src_value, state->fps_n,
79 GST_SECOND * state->fps_d);
80 res = TRUE;
83 /* FIXME add bytes <--> time */
85 return res;
88 gboolean
89 gst_base_video_encoded_video_convert (GstVideoState *state,
90 GstFormat src_format, gint64 src_value,
91 GstFormat * dest_format, gint64 *dest_value)
93 gboolean res = FALSE;
95 if (src_format == *dest_format) {
96 *dest_value = src_value;
97 return TRUE;
100 GST_ERROR("src convert");
102 #if 0
103 if (src_format == GST_FORMAT_DEFAULT && *dest_format == GST_FORMAT_TIME) {
104 if (dec->fps_d != 0) {
105 *dest_value = gst_util_uint64_scale (granulepos_to_frame (src_value),
106 dec->fps_d * GST_SECOND, dec->fps_n);
107 res = TRUE;
108 } else {
109 res = FALSE;
111 } else {
112 GST_ERROR("unhandled conversion from %d to %d", src_format, *dest_format);
113 res = FALSE;
115 #endif
117 return res;
120 gboolean
121 gst_base_video_state_from_caps (GstVideoState *state, GstCaps *caps)
124 gst_video_format_parse_caps (caps, &state->format,
125 &state->width, &state->height);
127 gst_video_parse_caps_framerate (caps, &state->fps_n, &state->fps_d);
129 state->par_n = 1;
130 state->par_d = 1;
131 gst_video_parse_caps_pixel_aspect_ratio (caps, &state->par_n,
132 &state->par_d);
134 /* FIXME handle this stuff some day */
135 state->interlaced = FALSE;
137 state->clean_width = state->width;
138 state->clean_height = state->height;
139 state->clean_offset_left = 0;
140 state->clean_offset_top = 0;
142 /* FIXME need better error handling */
143 return TRUE;
146 GstClockTime
147 gst_video_state_get_timestamp (const GstVideoState *state, int frame_number)
149 if (frame_number < 0) {
150 return state->segment.start -
151 (gint64)gst_util_uint64_scale (-frame_number,
152 state->fps_d * GST_SECOND, state->fps_n);
153 } else {
154 return state->segment.start +
155 gst_util_uint64_scale (frame_number,
156 state->fps_d * GST_SECOND, state->fps_n);
160 /* gst adapter */
162 static GSList *
163 get_chunk (GstAdapter *adapter, int offset, int *skip)
165 GSList *g;
167 #if 1
168 if (skip) *skip = 0;
169 #endif
171 g_return_val_if_fail (offset >= 0, NULL);
172 g_return_val_if_fail (offset < adapter->size, NULL);
174 offset += adapter->skip;
175 g = adapter->buflist;
176 while (g) {
177 if (offset < GST_BUFFER_SIZE(GST_BUFFER(g->data))) {
178 if (skip) *skip = offset;
179 return g;
181 offset -= GST_BUFFER_SIZE (GST_BUFFER(g->data));
182 g = g->next;
185 g_assert_not_reached ();
188 void
189 gst_adapter_copy_full (GstAdapter *adapter, void *dest, int offset,
190 int size)
192 int skip;
193 guint8 *cdest = dest;
194 int n_bytes;
195 GSList *g;
197 g_return_if_fail (offset >= 0);
198 g_return_if_fail (offset + size <= adapter->size);
200 g = get_chunk (adapter, offset, &skip);
201 while (size > 0) {
202 n_bytes = MIN (GST_BUFFER_SIZE(GST_BUFFER(g->data)) - skip,
203 size);
205 memcpy (cdest, GST_BUFFER_DATA(GST_BUFFER(g->data)) + skip,
206 n_bytes);
208 size -= n_bytes;
209 cdest += n_bytes;
210 skip = 0;
212 g = g->next;
216 static int
217 scan_fast (guint8 *data, guint32 pattern, guint32 mask, int n)
219 int i;
220 for(i=0;i<n;i++){
221 if ((GST_READ_UINT32_BE (data + i) & mask) == pattern) {
222 return i;
225 return n;
228 static gboolean
229 scan_slow (GstAdapter *adapter, GSList *g, int skip, guint32 pattern,
230 guint32 mask)
232 guint8 tmp[4];
233 int j;
235 for(j=0;j<4;j++){
236 tmp[j] = ((guint8 *)GST_BUFFER_DATA(GST_BUFFER(g->data)))[skip];
237 skip++;
238 if (skip >= GST_BUFFER_SIZE (GST_BUFFER(g->data))) {
239 g = g->next;
240 skip = 0;
244 return ((GST_READ_UINT32_BE (tmp) & mask) == pattern);
249 gst_adapter_masked_scan_uint32 (GstAdapter *adapter,
250 guint32 pattern, guint32 mask, int offset, int n)
252 GSList *g;
253 int j;
254 int k;
255 int skip;
256 int m;
258 g_return_val_if_fail (n >= 0, 0);
259 g_return_val_if_fail (offset >= 0, 0);
260 g_return_val_if_fail (offset + n + 4 <= adapter->size, 0);
262 g = get_chunk (adapter, offset, &skip);
263 j = 0;
264 while (j < n) {
265 m = MIN (GST_BUFFER_SIZE(GST_BUFFER(g->data)) - skip - 4, 0);
266 if (m > 0) {
267 k = scan_fast (GST_BUFFER_DATA(GST_BUFFER(g->data)) + skip,
268 pattern, mask, m);
269 if (k < m) {
270 return offset+j+k;
272 j += m;
273 skip += m;
274 } else {
275 if (scan_slow (adapter, g, skip, pattern, mask)) {
276 return offset + j;
278 j++;
279 skip++;
281 if (skip >= GST_BUFFER_SIZE (GST_BUFFER(g->data))) {
282 g = g->next;
283 skip = 0;
287 return n;
290 GstBuffer *
291 gst_adapter_get_buffer (GstAdapter *adapter)
293 return gst_buffer_ref (GST_BUFFER(adapter->buflist->data));