Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gst-plugins-base
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Sebastian Dröge
gst-plugins-base
Commits
a91b7f08
Commit
a91b7f08
authored
Apr 27, 2009
by
Michael Smith
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
theoradec: rearrange code in preparation for 422 and 444 support.
parent
f8370edc
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
114 additions
and
86 deletions
+114
-86
ext/theora/gsttheoradec.h
ext/theora/gsttheoradec.h
+1
-0
ext/theora/theoradec.c
ext/theora/theoradec.c
+113
-86
No files found.
ext/theora/gsttheoradec.h
View file @
a91b7f08
...
...
@@ -72,6 +72,7 @@ struct _GstTheoraDec
gboolean
need_keyframe
;
gint
width
,
height
;
gint
offset_x
,
offset_y
;
gint
output_bpp
;
gboolean
crop
;
...
...
ext/theora/theoradec.c
View file @
a91b7f08
...
...
@@ -66,7 +66,7 @@ GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC
,
GST_PAD_ALWAYS
,
GST_STATIC_CAPS
(
"video/x-raw-yuv, "
"format = (fourcc)
I420
, "
"format = (fourcc)
{ I420, YUY2, Y444 }
, "
"framerate = (fraction) [0/1, MAX], "
"width = (int) [ 1, MAX ], "
"height = (int) [ 1, MAX ]"
)
);
...
...
@@ -346,8 +346,8 @@ theora_dec_src_convert (GstPad * pad,
case
GST_FORMAT_BYTES
:
switch
(
*
dest_format
)
{
case
GST_FORMAT_DEFAULT
:
*
dest_value
=
gst_util_uint64_scale_int
(
src_value
,
2
,
dec
->
info
.
height
*
dec
->
info
.
width
*
3
);
*
dest_value
=
gst_util_uint64_scale_int
(
src_value
,
8
,
dec
->
info
.
height
*
dec
->
info
.
width
*
dec
->
output_bpp
);
break
;
case
GST_FORMAT_TIME
:
/* seems like a rather silly conversion, implement me if you like */
...
...
@@ -358,7 +358,7 @@ theora_dec_src_convert (GstPad * pad,
case
GST_FORMAT_TIME
:
switch
(
*
dest_format
)
{
case
GST_FORMAT_BYTES
:
scale
=
3
*
(
dec
->
info
.
width
*
dec
->
info
.
height
)
/
2
;
scale
=
dec
->
output_bpp
*
(
dec
->
info
.
width
*
dec
->
info
.
height
)
/
8
;
case
GST_FORMAT_DEFAULT
:
*
dest_value
=
scale
*
gst_util_uint64_scale
(
src_value
,
dec
->
info
.
fps_numerator
,
dec
->
info
.
fps_denominator
*
GST_SECOND
);
...
...
@@ -375,7 +375,7 @@ theora_dec_src_convert (GstPad * pad,
break
;
case
GST_FORMAT_BYTES
:
*
dest_value
=
gst_util_uint64_scale_int
(
src_value
,
3
*
dec
->
info
.
width
*
dec
->
info
.
height
,
2
);
dec
->
output_bpp
*
dec
->
info
.
width
*
dec
->
info
.
height
,
8
);
break
;
default:
res
=
FALSE
;
...
...
@@ -853,6 +853,7 @@ theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
GstFlowReturn
ret
=
GST_FLOW_OK
;
guint32
bitstream_version
;
GList
*
walk
;
guint32
fourcc
;
GST_DEBUG_OBJECT
(
dec
,
"fps %d/%d, PAR %d/%d"
,
dec
->
info
.
fps_numerator
,
dec
->
info
.
fps_denominator
,
...
...
@@ -888,10 +889,18 @@ theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
GST_DEBUG_OBJECT
(
dec
,
"frame dimension %dx%d, offset %d:%d"
,
dec
->
info
.
frame_width
,
dec
->
info
.
frame_height
,
dec
->
info
.
offset_x
,
dec
->
info
.
offset_y
);
if
(
dec
->
info
.
pixelformat
!=
OC_PF_420
)
{
GST_ELEMENT_ERROR
(
GST_ELEMENT
(
dec
),
STREAM
,
DECODE
,
(
NULL
),
(
"pixel formats other than 4:2:0 not yet supported"
));
if
(
dec
->
info
.
pixelformat
==
OC_PF_420
)
{
dec
->
output_bpp
=
12
;
/* Average bits per pixel. */
fourcc
=
GST_MAKE_FOURCC
(
'I'
,
'4'
,
'2'
,
'0'
);
}
else
if
(
dec
->
info
.
pixelformat
==
OC_PF_422
)
{
dec
->
output_bpp
=
16
;
fourcc
=
GST_MAKE_FOURCC
(
'Y'
,
'U'
,
'Y'
,
'2'
);
}
else
if
(
dec
->
info
.
pixelformat
==
OC_PF_444
)
{
dec
->
output_bpp
=
24
;
fourcc
=
GST_MAKE_FOURCC
(
'Y'
,
'4'
,
'4'
,
'4'
);
}
else
{
GST_ERROR_OBJECT
(
dec
,
"Invalid pixel format %d"
,
dec
->
info
.
pixelformat
);
return
GST_FLOW_ERROR
;
}
...
...
@@ -931,7 +940,7 @@ theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
theora_decode_init
(
&
dec
->
state
,
&
dec
->
info
);
caps
=
gst_caps_new_simple
(
"video/x-raw-yuv"
,
"format"
,
GST_TYPE_FOURCC
,
GST_MAKE_FOURCC
(
'I'
,
'4'
,
'2'
,
'0'
)
,
"format"
,
GST_TYPE_FOURCC
,
fourcc
,
"framerate"
,
GST_TYPE_FRACTION
,
dec
->
info
.
fps_numerator
,
dec
->
info
.
fps_denominator
,
"pixel-aspect-ratio"
,
GST_TYPE_FRACTION
,
par_num
,
par_den
,
...
...
@@ -1107,72 +1116,16 @@ theora_dec_push_reverse (GstTheoraDec * dec, GstBuffer * buf)
}
static
GstFlowReturn
theora_handle_data_packet
(
GstTheoraDec
*
dec
,
ogg_packet
*
packet
,
GstClockTime
outtime
)
theora_handle_420_image
(
GstTheoraDec
*
dec
,
yuv_buffer
*
yuv
,
GstBuffer
**
out
)
{
/* normal data packet */
yuv_buffer
yuv
;
GstBuffer
*
out
;
guint
i
;
gboolean
keyframe
;
gint
width
=
dec
->
width
;
gint
height
=
dec
->
height
;
gint
cwidth
=
width
/
2
;
gint
cheight
=
height
/
2
;
gint
out_size
;
gint
stride_y
,
stride_uv
;
gint
width
,
height
;
gint
cwidth
,
cheight
;
GstFlowReturn
result
;
if
(
G_UNLIKELY
(
!
dec
->
have_header
))
goto
not_initialized
;
/* the second most significant bit of the first data byte is cleared
* for keyframes. We can only check it if it's not a zero-length packet. */
keyframe
=
packet
->
bytes
&&
((
packet
->
packet
[
0
]
&
0x40
)
==
0
);
if
(
G_UNLIKELY
(
keyframe
))
{
GST_DEBUG_OBJECT
(
dec
,
"we have a keyframe"
);
dec
->
need_keyframe
=
FALSE
;
}
else
if
(
G_UNLIKELY
(
dec
->
need_keyframe
))
{
goto
dropping
;
}
GST_DEBUG_OBJECT
(
dec
,
"parsing data packet"
);
/* this does the decoding */
if
(
G_UNLIKELY
(
theora_decode_packetin
(
&
dec
->
state
,
packet
)))
goto
decode_error
;
if
(
outtime
!=
-
1
)
{
gboolean
need_skip
;
GstClockTime
qostime
;
/* qos needs to be done on running time */
qostime
=
gst_segment_to_running_time
(
&
dec
->
segment
,
GST_FORMAT_TIME
,
outtime
);
GST_OBJECT_LOCK
(
dec
);
/* check for QoS, don't perform the last steps of getting and
* pushing the buffers that are known to be late. */
/* FIXME, we can also entirely skip decoding if the next valid buffer is
* known to be after a keyframe (using the granule_shift) */
need_skip
=
dec
->
earliest_time
!=
-
1
&&
qostime
<=
dec
->
earliest_time
;
GST_OBJECT_UNLOCK
(
dec
);
if
(
need_skip
)
goto
dropping_qos
;
}
/* this does postprocessing and set up the decoded frame
* pointers in our yuv variable */
if
(
G_UNLIKELY
(
theora_decode_YUVout
(
&
dec
->
state
,
&
yuv
)
<
0
))
goto
no_yuv
;
if
(
G_UNLIKELY
((
yuv
.
y_width
!=
dec
->
info
.
width
)
||
(
yuv
.
y_height
!=
dec
->
info
.
height
)))
goto
wrong_dimensions
;
width
=
dec
->
width
;
height
=
dec
->
height
;
cwidth
=
width
/
2
;
cheight
=
height
/
2
;
int
i
;
/* should get the stride from the caps, for now we round up to the nearest
* multiple of 4 because some element needs it. chroma needs special
...
...
@@ -1187,7 +1140,7 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
* frame_width, frame_height */
result
=
gst_pad_alloc_buffer_and_set_caps
(
dec
->
srcpad
,
GST_BUFFER_OFFSET_NONE
,
out_size
,
GST_PAD_CAPS
(
dec
->
srcpad
),
&
out
);
out_size
,
GST_PAD_CAPS
(
dec
->
srcpad
),
out
);
if
(
G_UNLIKELY
(
result
!=
GST_FLOW_OK
))
goto
no_buffer
;
...
...
@@ -1204,7 +1157,7 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
guchar
*
dest_v
,
*
src_v
;
gint
offset
;
dest_y
=
GST_BUFFER_DATA
(
out
);
dest_y
=
GST_BUFFER_DATA
(
*
out
);
dest_u
=
dest_y
+
stride_y
*
GST_ROUND_UP_2
(
height
);
dest_v
=
dest_u
+
stride_uv
*
GST_ROUND_UP_2
(
height
)
/
2
;
...
...
@@ -1212,30 +1165,110 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
GST_LOG_OBJECT
(
dec
,
"plane 1, offset %d"
,
dest_u
-
dest_y
);
GST_LOG_OBJECT
(
dec
,
"plane 2, offset %d"
,
dest_v
-
dest_y
);
src_y
=
yuv
.
y
+
dec
->
offset_x
+
dec
->
offset_y
*
yuv
.
y_stride
;
src_y
=
yuv
->
y
+
dec
->
offset_x
+
dec
->
offset_y
*
yuv
->
y_stride
;
for
(
i
=
0
;
i
<
height
;
i
++
)
{
memcpy
(
dest_y
,
src_y
,
width
);
dest_y
+=
stride_y
;
src_y
+=
yuv
.
y_stride
;
src_y
+=
yuv
->
y_stride
;
}
offset
=
dec
->
offset_x
/
2
+
dec
->
offset_y
/
2
*
yuv
.
uv_stride
;
offset
=
dec
->
offset_x
/
2
+
dec
->
offset_y
/
2
*
yuv
->
uv_stride
;
src_u
=
yuv
.
u
+
offset
;
src_v
=
yuv
.
v
+
offset
;
src_u
=
yuv
->
u
+
offset
;
src_v
=
yuv
->
v
+
offset
;
for
(
i
=
0
;
i
<
cheight
;
i
++
)
{
memcpy
(
dest_u
,
src_u
,
cwidth
);
memcpy
(
dest_v
,
src_v
,
cwidth
);
dest_u
+=
stride_uv
;
src_u
+=
yuv
.
uv_stride
;
src_u
+=
yuv
->
uv_stride
;
dest_v
+=
stride_uv
;
src_v
+=
yuv
.
uv_stride
;
src_v
+=
yuv
->
uv_stride
;
}
}
no_buffer:
{
GST_DEBUG_OBJECT
(
dec
,
"could not get buffer, reason: %s"
,
gst_flow_get_name
(
result
));
return
result
;
}
}
static
GstFlowReturn
theora_handle_data_packet
(
GstTheoraDec
*
dec
,
ogg_packet
*
packet
,
GstClockTime
outtime
)
{
/* normal data packet */
yuv_buffer
yuv
;
GstBuffer
*
out
;
gboolean
keyframe
;
GstFlowReturn
result
;
if
(
G_UNLIKELY
(
!
dec
->
have_header
))
goto
not_initialized
;
/* the second most significant bit of the first data byte is cleared
* for keyframes. We can only check it if it's not a zero-length packet. */
keyframe
=
packet
->
bytes
&&
((
packet
->
packet
[
0
]
&
0x40
)
==
0
);
if
(
G_UNLIKELY
(
keyframe
))
{
GST_DEBUG_OBJECT
(
dec
,
"we have a keyframe"
);
dec
->
need_keyframe
=
FALSE
;
}
else
if
(
G_UNLIKELY
(
dec
->
need_keyframe
))
{
goto
dropping
;
}
GST_DEBUG_OBJECT
(
dec
,
"parsing data packet"
);
/* this does the decoding */
if
(
G_UNLIKELY
(
theora_decode_packetin
(
&
dec
->
state
,
packet
)))
goto
decode_error
;
if
(
outtime
!=
-
1
)
{
gboolean
need_skip
;
GstClockTime
qostime
;
/* qos needs to be done on running time */
qostime
=
gst_segment_to_running_time
(
&
dec
->
segment
,
GST_FORMAT_TIME
,
outtime
);
GST_OBJECT_LOCK
(
dec
);
/* check for QoS, don't perform the last steps of getting and
* pushing the buffers that are known to be late. */
/* FIXME, we can also entirely skip decoding if the next valid buffer is
* known to be after a keyframe (using the granule_shift) */
need_skip
=
dec
->
earliest_time
!=
-
1
&&
qostime
<=
dec
->
earliest_time
;
GST_OBJECT_UNLOCK
(
dec
);
if
(
need_skip
)
goto
dropping_qos
;
}
/* this does postprocessing and set up the decoded frame
* pointers in our yuv variable */
if
(
G_UNLIKELY
(
theora_decode_YUVout
(
&
dec
->
state
,
&
yuv
)
<
0
))
goto
no_yuv
;
if
(
G_UNLIKELY
((
yuv
.
y_width
!=
dec
->
info
.
width
)
||
(
yuv
.
y_height
!=
dec
->
info
.
height
)))
goto
wrong_dimensions
;
if
(
dec
->
info
.
pixelformat
==
OC_PF_420
)
{
result
=
theora_handle_420_image
(
dec
,
&
yuv
,
&
out
);
#if 0
} else if (dec->info.pixelformat == OC_PF_422) {
result = theora_handle_422_image (dec, &yuv, &out);
} else if (dec->info.pixelformat == OC_PF_444) {
result = theora_handle_444_image (dec, &yuv, &out);
} else {
g_assert_not_reached ();
#endif
}
if
(
result
!=
GST_FLOW_OK
)
return
result
;
GST_BUFFER_OFFSET
(
out
)
=
dec
->
frame_nr
;
if
(
dec
->
frame_nr
!=
-
1
)
...
...
@@ -1299,12 +1332,6 @@ wrong_dimensions:
(
NULL
),
(
"dimensions of image do not match header"
));
return
GST_FLOW_ERROR
;
}
no_buffer:
{
GST_DEBUG_OBJECT
(
dec
,
"could not get buffer, reason: %s"
,
gst_flow_get_name
(
result
));
return
result
;
}
}
static
GstFlowReturn
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment