Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Xiph.Org
Cortado
Commits
480f992e
Commit
480f992e
authored
Feb 18, 2010
by
Gregory Maxwell
Committed by
ogg.k.ogg.k
Mar 15, 2010
Browse files
Completes handling of drop frames; preserves timing.
Avoids displaying duplicate frames, except once per second.
parent
e08167a4
Changes
4
Hide whitespace changes
Inline
Side-by-side
src/com/fluendo/jheora/State.java
View file @
480f992e
...
...
@@ -65,45 +65,47 @@ public class State
pbi
.
DecoderErrorCode
=
0
;
pbi
.
opb
.
readinit
(
op
.
packet_base
,
op
.
packet
,
op
.
bytes
);
/* verify that this is a video frame */
ret
=
pbi
.
opb
.
readB
(
1
);
if
(
ret
==
0
)
{
try
{
ret
=
dec
.
loadAndDecode
();
}
catch
(
Exception
e
)
{
/* If lock onto the bitstream is lost all sort of Exceptions can occur.
* The bitstream damage may be local, so the next packet may be okay. */
e
.
printStackTrace
();
return
Result
.
BADPACKET
;
}
if
(
op
.
bytes
>
0
)
{
pbi
.
opb
.
readinit
(
op
.
packet_base
,
op
.
packet
,
op
.
bytes
);
/* verify that this is a video frame */
ret
=
pbi
.
opb
.
readB
(
1
);
if
(
ret
==
0
)
{
try
{
ret
=
dec
.
loadAndDecode
();
}
catch
(
Exception
e
)
{
/* If lock onto the bitstream is lost all sort of Exceptions can occur.
* The bitstream damage may be local, so the next packet may be okay. */
e
.
printStackTrace
();
return
Result
.
BADPACKET
;
}
if
(
ret
!=
0
)
return
(
int
)
ret
;
if
(
ret
!=
0
)
return
(
int
)
ret
;
if
(
op
.
granulepos
>-
1
)
granulepos
=
op
.
granulepos
;
else
{
if
(
granulepos
==-
1
){
granulepos
=
0
;
}
else
{
if
(
pbi
.
FrameType
==
Constants
.
BASE_FRAME
){
long
frames
=
granulepos
&
((
1
<<
pbi
.
keyframe_granule_shift
)-
1
);
granulepos
>>=
pbi
.
keyframe_granule_shift
;
granulepos
+=
frames
+
1
;
granulepos
<<=
pbi
.
keyframe_granule_shift
;
}
else
granulepos
++;
}
}
else
{
return
Result
.
BADPACKET
;
}
return
(
0
);
}
}
if
(
op
.
granulepos
>-
1
)
granulepos
=
op
.
granulepos
;
else
{
if
(
granulepos
==-
1
){
granulepos
=
0
;
}
else
{
if
((
op
.
bytes
>
0
)
&&
(
pbi
.
FrameType
==
Constants
.
BASE_FRAME
)){
long
frames
=
granulepos
&
((
1
<<
pbi
.
keyframe_granule_shift
)-
1
);
granulepos
>>=
pbi
.
keyframe_granule_shift
;
granulepos
+=
frames
+
1
;
granulepos
<<=
pbi
.
keyframe_granule_shift
;
}
else
granulepos
++;
}
}
return
Result
.
BADPACKET
;
return
(
0
)
;
}
public
int
decodeYUVout
(
YUVBuffer
yuv
)
...
...
src/com/fluendo/jst/Buffer.java
View file @
480f992e
...
...
@@ -38,6 +38,7 @@ public class Buffer {
public
long
time_offset
;
public
long
timestamp
;
public
long
timestampEnd
;
public
boolean
duplicate
=
false
;
public
static
Buffer
create
()
{
Buffer
result
;
...
...
src/com/fluendo/plugin/TheoraDec.java
View file @
480f992e
...
...
@@ -34,8 +34,10 @@ public class TheoraDec extends Element implements OggPayload
private
Packet
op
;
private
int
packet
;
private
YUVBuffer
yuv
;
private
java
.
lang
.
Object
last_yuv_obj
;
private
long
lastTs
;
private
long
lastnondupe
=
-
1
;
private
boolean
needKeyframe
;
private
boolean
haveBOS
=
false
;
private
boolean
haveDecoder
=
false
;
...
...
@@ -197,18 +199,6 @@ public class TheoraDec extends Element implements OggPayload
return
OK
;
}
else
{
if
(
op
.
bytes
==
0
)
{
Debug
.
log
(
Debug
.
DEBUG
,
"duplicate frame"
);
return
OK
;
}
if
((
op
.
packet_base
[
op
.
packet
]
&
0x80
)
==
0x80
)
{
Debug
.
log
(
Debug
.
INFO
,
"ignoring header"
);
return
OK
;
}
if
(
needKeyframe
&&
ts
.
isKeyframe
(
op
))
{
needKeyframe
=
false
;
}
if
(
timestamp
!=
-
1
)
{
lastTs
=
timestamp
;
}
...
...
@@ -220,18 +210,41 @@ public class TheoraDec extends Element implements OggPayload
timestamp
=
lastTs
;
}
if
(
op
.
bytes
>
0
)
{
if
((
op
.
packet_base
[
op
.
packet
]
&
0x80
)
==
0x80
)
{
Debug
.
log
(
Debug
.
INFO
,
"ignoring header"
);
return
OK
;
}
if
(
needKeyframe
&&
ts
.
isKeyframe
(
op
))
{
needKeyframe
=
false
;
}
}
else
{
Debug
.
log
(
Debug
.
DEBUG
,
"duplicate frame"
);
}
if
(!
needKeyframe
)
{
try
{
if
(
ts
.
decodePacketin
(
op
)
!=
0
)
{
Debug
.
log
(
Debug
.
ERROR
,
"Bad Theora packet. Most likely not fatal, hoping for better luck next packet."
);
}
if
(
ts
.
decodeYUVout
(
yuv
)
!=
0
)
{
buf
.
free
();
postMessage
(
Message
.
newError
(
this
,
"Error getting the Theora picture"
));
Debug
.
log
(
Debug
.
ERROR
,
"Error getting the picture."
);
return
ERROR
;
if
(
op
.
bytes
>
0
)
{
if
(
ts
.
decodeYUVout
(
yuv
)
!=
0
)
{
buf
.
free
();
postMessage
(
Message
.
newError
(
this
,
"Error getting the Theora picture"
));
Debug
.
log
(
Debug
.
ERROR
,
"Error getting the picture."
);
return
ERROR
;
}
buf
.
duplicate
=
false
;
lastnondupe
=
timestamp
;
last_yuv_obj
=
yuv
.
getObject
(
ti
.
offset_x
,
ti
.
offset_y
,
ti
.
frame_width
,
ti
.
frame_height
);
}
else
{
if
(
timestamp
-
lastnondupe
>=
Clock
.
SECOND
)
{
buf
.
duplicate
=
false
;
lastnondupe
=
timestamp
;
}
else
buf
.
duplicate
=
true
;
}
buf
.
object
=
yuv
.
getObject
(
ti
.
offset_x
,
ti
.
offset_y
,
ti
.
frame_width
,
ti
.
frame_height
)
;
buf
.
object
=
last_yuv_obj
;
buf
.
caps
=
caps
;
buf
.
timestamp
=
timestamp
;
Debug
.
log
(
Debug
.
DEBUG
,
parent
.
getName
()
+
" >>> "
+
buf
);
...
...
src/com/fluendo/plugin/VideoSink.java
View file @
480f992e
...
...
@@ -83,64 +83,65 @@ public class VideoSink extends Sink
Image
image
;
int
x
,
y
,
w
,
h
;
Debug
.
log
(
Debug
.
DEBUG
,
this
.
getName
()
+
" starting buffer "
+
buf
);
if
(!
buf
.
duplicate
)
{
Debug
.
log
(
Debug
.
DEBUG
,
this
.
getName
()
+
" starting buffer "
+
buf
);
if
(
buf
.
object
instanceof
ImageProducer
)
{
image
=
component
.
createImage
((
ImageProducer
)
buf
.
object
);
}
else
if
(
buf
.
object
instanceof
Image
)
{
image
=
(
Image
)
buf
.
object
;
}
else
{
System
.
out
.
println
(
this
+
": unknown buffer received "
+
buf
);
return
Pad
.
ERROR
;
}
if
(!
component
.
isVisible
())
return
Pad
.
NOT_NEGOTIATED
;
Graphics
graphics
=
component
.
getGraphics
();
if
(
keepAspect
)
{
double
src_ratio
,
dst_ratio
;
if
(
bounds
==
null
)
{
bounds
=
new
Rectangle
(
component
.
getSize
());
if
(
buf
.
object
instanceof
ImageProducer
)
{
image
=
component
.
createImage
((
ImageProducer
)
buf
.
object
);
}
else
if
(
buf
.
object
instanceof
Image
)
{
image
=
(
Image
)
buf
.
object
;
}
else
{
System
.
out
.
println
(
this
+
": unknown buffer received "
+
buf
);
return
Pad
.
ERROR
;
}
src_ratio
=
(
double
)
width
/
height
;
dst_ratio
=
(
double
)
bounds
.
width
/
bounds
.
height
;
if
(
src_ratio
>
dst_ratio
)
{
w
=
bounds
.
width
;
h
=
(
int
)
(
bounds
.
width
/
src_ratio
);
x
=
bounds
.
x
;
y
=
bounds
.
y
+
(
bounds
.
height
-
h
)
/
2
;
}
else
if
(
src_ratio
<
dst_ratio
)
{
w
=
(
int
)
(
bounds
.
height
*
src_ratio
);
h
=
bounds
.
height
;
if
(!
component
.
isVisible
())
return
Pad
.
NOT_NEGOTIATED
;
Graphics
graphics
=
component
.
getGraphics
();
if
(
keepAspect
)
{
double
src_ratio
,
dst_ratio
;
if
(
bounds
==
null
)
{
bounds
=
new
Rectangle
(
component
.
getSize
());
}
src_ratio
=
(
double
)
width
/
height
;
dst_ratio
=
(
double
)
bounds
.
width
/
bounds
.
height
;
if
(
src_ratio
>
dst_ratio
)
{
w
=
bounds
.
width
;
h
=
(
int
)
(
bounds
.
width
/
src_ratio
);
x
=
bounds
.
x
;
y
=
bounds
.
y
+
(
bounds
.
height
-
h
)
/
2
;
}
else
if
(
src_ratio
<
dst_ratio
)
{
w
=
(
int
)
(
bounds
.
height
*
src_ratio
);
h
=
bounds
.
height
;
x
=
bounds
.
x
+
(
bounds
.
width
-
w
)
/
2
;
y
=
bounds
.
y
;
}
else
{
x
=
bounds
.
x
;
y
=
bounds
.
y
;
w
=
bounds
.
width
;
h
=
bounds
.
height
;
}
}
else
if
(!
scale
)
{
w
=
Math
.
min
(
width
,
bounds
.
width
);
h
=
Math
.
min
(
height
,
bounds
.
height
);
x
=
bounds
.
x
+
(
bounds
.
width
-
w
)
/
2
;
y
=
bounds
.
y
;
y
=
bounds
.
y
+
(
bounds
.
height
-
h
)
/
2
;
}
else
{
x
=
bounds
.
x
;
y
=
bounds
.
y
;
/* draw in available area */
w
=
bounds
.
width
;
h
=
bounds
.
height
;
x
=
0
;
y
=
0
;
}
}
else
if
(!
scale
)
{
w
=
Math
.
min
(
width
,
bounds
.
width
);
h
=
Math
.
min
(
height
,
bounds
.
height
);
x
=
bounds
.
x
+
(
bounds
.
width
-
w
)
/
2
;
y
=
bounds
.
y
+
(
bounds
.
height
-
h
)
/
2
;
}
else
{
/* draw in available area */
w
=
bounds
.
width
;
h
=
bounds
.
height
;
x
=
0
;
y
=
0
;
graphics
.
drawImage
(
image
,
x
,
y
,
w
,
h
,
null
);
Debug
.
log
(
Debug
.
DEBUG
,
this
.
getName
()
+
" done with buffer "
+
buf
);
}
graphics
.
drawImage
(
image
,
x
,
y
,
w
,
h
,
null
);
Debug
.
log
(
Debug
.
DEBUG
,
this
.
getName
()
+
" done with buffer "
+
buf
);
return
Pad
.
OK
;
};
...
...
Write
Preview
Supports
Markdown
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