Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-gpu
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
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
videolan
vlc-gpu
Commits
7cc81487
Commit
7cc81487
authored
Sep 01, 2008
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Revert "Improved rtjpeg and seek NUV demuxer support.""
This reverts commit
bebc7751
.
parent
34967bbd
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
313 additions
and
84 deletions
+313
-84
modules/demux/nuv.c
modules/demux/nuv.c
+313
-84
No files found.
modules/demux/nuv.c
View file @
7cc81487
...
@@ -5,6 +5,7 @@
...
@@ -5,6 +5,7 @@
* $Id$
* $Id$
*
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Gertjan Van Droogenbroeck <gertjanvd _PLUS_ vlc _AT_ gmail _DOT_ com>
*
*
* This program is free software; you can redistribute it and/or modify
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU General Public License as published by
...
@@ -33,9 +34,6 @@
...
@@ -33,9 +34,6 @@
#include <vlc_demux.h>
#include <vlc_demux.h>
/* TODO:
/* TODO:
* - complete support (add support for rtjpeg and raw)
* - better seek support (to key frame)
* - control GET_LENGTH (harder, unless we have an extended header+index)
* - test
* - test
*/
*/
...
@@ -111,11 +109,13 @@ typedef struct
...
@@ -111,11 +109,13 @@ typedef struct
}
header_t
;
}
header_t
;
#define NUV_FH_SIZE 12
typedef
struct
typedef
struct
{
{
char
i_type
;
/* A: audio, V: video, S: sync; T: test
char
i_type
;
/* A: audio, V: video, S: sync; T: test
R: Seekpoint (string:RTjjjjjjjj)
R: Seekpoint (string:RTjjjjjjjj)
D: Extra data for codec */
D: Extra data for codec
X: extended data Q: seektable */
char
i_compression
;
/* V: 0 uncompressed
char
i_compression
;
/* V: 0 uncompressed
1 RTJpeg
1 RTJpeg
2 RTJpeg+lzo
2 RTJpeg+lzo
...
@@ -146,7 +146,6 @@ typedef struct
...
@@ -146,7 +146,6 @@ typedef struct
S: length of packet correl */
S: length of packet correl */
}
frame_header_t
;
}
frame_header_t
;
/* FIXME Not sure of this one */
typedef
struct
typedef
struct
{
{
int
i_version
;
int
i_version
;
...
@@ -165,7 +164,7 @@ typedef struct
...
@@ -165,7 +164,7 @@ typedef struct
int
i_lavc_qmin
;
int
i_lavc_qmin
;
int
i_lavc_qmax
;
int
i_lavc_qmax
;
int
i_lavc_maxqdiff
;
int
i_lavc_maxqdiff
;
int64_t
i_seekable_offset
;
int64_t
i_seek
t
able_offset
;
int64_t
i_keyframe_adjust_offset
;
int64_t
i_keyframe_adjust_offset
;
}
extended_header_t
;
}
extended_header_t
;
...
@@ -184,11 +183,21 @@ struct demux_sys_t
...
@@ -184,11 +183,21 @@ struct demux_sys_t
/* index */
/* index */
demux_index_t
idx
;
demux_index_t
idx
;
bool
b_index
;
bool
b_seekable
;
/* frameheader buffer */
uint8_t
fh_buffer
[
NUV_FH_SIZE
];
int64_t
i_total_frames
;
int64_t
i_total_length
;
/* first frame position (used for calculating size without seektable) */
int
i_first_frame_offset
;
};
};
static
int
HeaderLoad
(
demux_t
*
,
header_t
*
h
);
static
int
HeaderLoad
(
demux_t
*
,
header_t
*
h
);
static
int
FrameHeaderLoad
(
demux_t
*
,
frame_header_t
*
h
);
static
int
FrameHeaderLoad
(
demux_t
*
,
frame_header_t
*
h
);
static
int
ExtendedHeaderLoad
(
demux_t
*
,
extended_header_t
*
h
);
static
int
ExtendedHeaderLoad
(
demux_t
*
,
extended_header_t
*
h
);
static
int
SeekTableLoad
(
demux_t
*
,
demux_sys_t
*
);
static
int
ControlSetPosition
(
demux_t
*
p_demux
,
int64_t
i_pos
,
bool
b_guess
);
/*****************************************************************************
/*****************************************************************************
* Open: initializes ES structures
* Open: initializes ES structures
...
@@ -208,13 +217,29 @@ static int Open( vlc_object_t * p_this )
...
@@ -208,13 +217,29 @@ static int Open( vlc_object_t * p_this )
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
p_sys
=
malloc
(
sizeof
(
demux_sys_t
)
);
p_sys
=
malloc
(
sizeof
(
demux_sys_t
)
);
if
(
p_sys
==
NULL
)
return
VLC_ENOMEM
;
memset
(
p_sys
,
0
,
sizeof
(
demux_sys_t
)
);
memset
(
p_sys
,
0
,
sizeof
(
demux_sys_t
)
);
p_sys
->
p_es_video
=
NULL
;
p_sys
->
p_es_video
=
NULL
;
p_sys
->
p_es_audio
=
NULL
;
p_sys
->
p_es_audio
=
NULL
;
p_sys
->
p_extra_f
=
NULL
;
p_sys
->
p_extra_f
=
NULL
;
p_sys
->
i_pcr
=
-
1
;
p_sys
->
i_pcr
=
-
1
;
p_sys
->
b_index
=
false
;
p_sys
->
i_total_frames
=
-
1
;
p_sys
->
i_total_length
=
-
1
;
demux_IndexInit
(
&
p_sys
->
idx
);
demux_IndexInit
(
&
p_sys
->
idx
);
p_demux
->
p_sys
=
p_sys
;
/* Info about the stream */
stream_Control
(
p_demux
->
s
,
STREAM_CAN_SEEK
,
&
p_sys
->
b_seekable
);
#if 0
if( p_sys->b_seekable )
msg_Dbg( p_demux, "stream is seekable" );
else
msg_Dbg( p_demux, "stream is NOT seekable" );
#endif
if
(
HeaderLoad
(
p_demux
,
&
p_sys
->
hdr
)
)
if
(
HeaderLoad
(
p_demux
,
&
p_sys
->
hdr
)
)
goto
error
;
goto
error
;
...
@@ -223,18 +248,17 @@ static int Open( vlc_object_t * p_this )
...
@@ -223,18 +248,17 @@ static int Open( vlc_object_t * p_this )
goto
error
;
goto
error
;
if
(
fh
.
i_length
>
0
)
if
(
fh
.
i_length
>
0
)
{
{
if
(
fh
.
i_compression
==
'F'
)
if
(
fh
.
i_compression
==
'F'
||
fh
.
i_compression
==
'R'
)
{
{
/* ffmpeg extra data */
/* ffmpeg extra data */
p_sys
->
i_extra_f
=
fh
.
i_length
;
p_sys
->
i_extra_f
=
fh
.
i_length
;
p_sys
->
p_extra_f
=
malloc
(
fh
.
i_length
);
p_sys
->
p_extra_f
=
malloc
(
fh
.
i_length
);
if
(
stream_Read
(
p_demux
->
s
,
if
(
p_sys
->
p_extra_f
==
NULL
||
stream_Read
(
p_demux
->
s
,
p_sys
->
p_extra_f
,
fh
.
i_length
)
!=
fh
.
i_length
)
p_sys
->
p_extra_f
,
fh
.
i_length
)
!=
fh
.
i_length
)
goto
error
;
goto
error
;
}
}
else
else
{
{
/* TODO handle rtjpeg */
msg_Warn
(
p_demux
,
"unsupported 'D' frame (c=%c)"
,
fh
.
i_compression
);
msg_Warn
(
p_demux
,
"unsupported 'D' frame (c=%c)"
,
fh
.
i_compression
);
if
(
stream_Read
(
p_demux
->
s
,
NULL
,
fh
.
i_length
)
!=
fh
.
i_length
)
if
(
stream_Read
(
p_demux
->
s
,
NULL
,
fh
.
i_length
)
!=
fh
.
i_length
)
goto
error
;
goto
error
;
...
@@ -256,6 +280,11 @@ static int Open( vlc_object_t * p_this )
...
@@ -256,6 +280,11 @@ static int Open( vlc_object_t * p_this )
if
(
ExtendedHeaderLoad
(
p_demux
,
&
p_sys
->
exh
)
)
if
(
ExtendedHeaderLoad
(
p_demux
,
&
p_sys
->
exh
)
)
goto
error
;
goto
error
;
if
(
!
p_sys
->
b_seekable
)
msg_Warn
(
p_demux
,
"stream is not seekable, skipping seektable"
);
else
if
(
SeekTableLoad
(
p_demux
,
p_sys
)
)
goto
error
;
}
}
else
else
{
{
...
@@ -277,6 +306,7 @@ static int Open( vlc_object_t * p_this )
...
@@ -277,6 +306,7 @@ static int Open( vlc_object_t * p_this )
fmt
.
video
.
i_height
=
p_sys
->
hdr
.
i_height
;
fmt
.
video
.
i_height
=
p_sys
->
hdr
.
i_height
;
fmt
.
i_extra
=
p_sys
->
i_extra_f
;
fmt
.
i_extra
=
p_sys
->
i_extra_f
;
fmt
.
p_extra
=
p_sys
->
p_extra_f
;
fmt
.
p_extra
=
p_sys
->
p_extra_f
;
fmt
.
video
.
i_aspect
=
VOUT_ASPECT_FACTOR
*
p_sys
->
hdr
.
d_aspect
;
p_sys
->
p_es_video
=
es_out_Add
(
p_demux
->
out
,
&
fmt
);
p_sys
->
p_es_video
=
es_out_Add
(
p_demux
->
out
,
&
fmt
);
}
}
...
@@ -295,16 +325,17 @@ static int Open( vlc_object_t * p_this )
...
@@ -295,16 +325,17 @@ static int Open( vlc_object_t * p_this )
msg_Warn
(
p_demux
,
"text not yet supported (upload samples)"
);
msg_Warn
(
p_demux
,
"text not yet supported (upload samples)"
);
}
}
p_sys
->
i_first_frame_offset
=
stream_Tell
(
p_demux
->
s
);
/* Fill p_demux fields */
/* Fill p_demux fields */
p_demux
->
pf_demux
=
Demux
;
p_demux
->
pf_demux
=
Demux
;
p_demux
->
pf_control
=
Control
;
p_demux
->
pf_control
=
Control
;
p_demux
->
p_sys
=
p_sys
;
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
error:
error:
msg_Warn
(
p_demux
,
"cannot load Nuv file"
);
msg_Warn
(
p_demux
,
"cannot load Nuv file"
);
p_demux
->
p_sys
=
NULL
;
free
(
p_sys
);
free
(
p_sys
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
...
@@ -346,9 +377,10 @@ static int Demux( demux_t *p_demux )
...
@@ -346,9 +377,10 @@ static int Demux( demux_t *p_demux )
/* TODO add support for some block type */
/* TODO add support for some block type */
if
(
fh
.
i_type
!=
'R'
)
if
(
fh
.
i_type
!=
'R'
&&
fh
.
i_length
>
0
)
{
{
stream_Read
(
p_demux
->
s
,
NULL
,
fh
.
i_length
);
if
(
stream_Read
(
p_demux
->
s
,
NULL
,
fh
.
i_length
)
!=
fh
.
i_length
)
return
-
1
;
}
}
}
}
...
@@ -357,8 +389,9 @@ static int Demux( demux_t *p_demux )
...
@@ -357,8 +389,9 @@ static int Demux( demux_t *p_demux )
p_data
->
i_dts
=
(
int64_t
)
fh
.
i_timecode
*
1000
;
p_data
->
i_dts
=
(
int64_t
)
fh
.
i_timecode
*
1000
;
p_data
->
i_pts
=
(
fh
.
i_type
==
'V'
)
?
0
:
p_data
->
i_dts
;
p_data
->
i_pts
=
(
fh
.
i_type
==
'V'
)
?
0
:
p_data
->
i_dts
;
/* */
/* only add keyframes to index */
demux_IndexAppend
(
&
p_sys
->
idx
,
p_data
->
i_dts
,
stream_Tell
(
p_demux
->
s
)
);
if
(
!
fh
.
i_keyframe
&&
!
p_sys
->
b_index
)
demux_IndexAppend
(
&
p_sys
->
idx
,
p_data
->
i_dts
,
stream_Tell
(
p_demux
->
s
)
-
NUV_FH_SIZE
);
/* */
/* */
if
(
p_data
->
i_dts
>
p_sys
->
i_pcr
)
if
(
p_data
->
i_dts
>
p_sys
->
i_pcr
)
...
@@ -379,7 +412,14 @@ static int Demux( demux_t *p_demux )
...
@@ -379,7 +412,14 @@ static int Demux( demux_t *p_demux )
}
}
else
if
(
fh
.
i_type
==
'V'
&&
p_sys
->
p_es_video
)
else
if
(
fh
.
i_type
==
'V'
&&
p_sys
->
p_es_video
)
{
{
if
(
fh
.
i_compression
>=
'4'
)
if
(
fh
.
i_compression
>=
'0'
&&
fh
.
i_compression
<=
'3'
)
{
/* for rtjpeg data, the header is also needed */
p_data
=
block_Realloc
(
p_data
,
NUV_FH_SIZE
,
fh
.
i_length
);
memcpy
(
p_data
->
p_buffer
,
p_sys
->
fh_buffer
,
NUV_FH_SIZE
);
}
/* 0,1,2,3 -> rtjpeg, >=4 mpeg4 */
if
(
fh
.
i_compression
>=
'0'
)
es_out_Send
(
p_demux
->
out
,
p_sys
->
p_es_video
,
p_data
);
es_out_Send
(
p_demux
->
out
,
p_sys
->
p_es_video
,
p_data
);
else
else
{
{
...
@@ -410,11 +450,19 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
...
@@ -410,11 +450,19 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
case
DEMUX_GET_POSITION
:
case
DEMUX_GET_POSITION
:
pf
=
(
double
*
)
va_arg
(
args
,
double
*
);
pf
=
(
double
*
)
va_arg
(
args
,
double
*
);
if
(
p_sys
->
i_total_length
>
0
&&
p_sys
->
i_pcr
>=
0
)
{
*
pf
=
(
double
)
p_sys
->
i_pcr
/
(
double
)
p_sys
->
i_total_length
;
}
else
{
i64
=
stream_Size
(
p_demux
->
s
);
i64
=
stream_Size
(
p_demux
->
s
);
if
(
i64
>
0
)
if
(
i64
>
0
)
*
pf
=
(
double
)
stream_Tell
(
p_demux
->
s
)
/
(
double
)
i64
;
*
pf
=
(
double
)
stream_Tell
(
p_demux
->
s
)
/
(
double
)
i64
;
else
else
*
pf
=
0
.
0
;
*
pf
=
0
.
0
;
}
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
case
DEMUX_SET_POSITION
:
case
DEMUX_SET_POSITION
:
...
@@ -422,47 +470,24 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
...
@@ -422,47 +470,24 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
int64_t
i_pos
;
int64_t
i_pos
;
f
=
(
double
)
va_arg
(
args
,
double
);
f
=
(
double
)
va_arg
(
args
,
double
);
i_pos
=
stream_Size
(
p_demux
->
s
)
*
f
;
i64
=
demux_IndexFindOffset
(
&
p_sys
->
idx
,
i_pos
);
p_sys
->
i_pcr
=
-
1
;
p_sys
->
i_pcr
=
-
1
;
if
(
i64
>=
0
)
/* first try to see if we can seek based on time (== GET_LENGTH works) */
return
stream_Seek
(
p_demux
->
s
,
i64
);
if
(
p_sys
->
i_total_length
>
0
&&
(
i_pos
=
demux_IndexConvertTime
(
&
p_sys
->
idx
,
p_sys
->
i_total_length
*
f
)
)
>
0
)
return
ControlSetPosition
(
p_demux
,
i_pos
,
false
);
if
(
p_sys
->
idx
.
i_idx
>
0
)
/* if not search based on total stream size */
{
else
if
(
(
i_pos
=
demux_IndexFindOffset
(
&
p_sys
->
idx
,
stream_Size
(
p_demux
->
s
)
*
f
)
)
>=
0
)
if
(
stream_Seek
(
p_demux
->
s
,
p_sys
->
idx
.
idx
[
p_sys
->
idx
.
i_idx
-
1
].
i_offset
)
)
return
ControlSetPosition
(
p_demux
,
i_pos
,
false
);
return
VLC_EGENERIC
;
}
else
{
if
(
stream_Seek
(
p_demux
->
s
,
0
)
)
return
VLC_EGENERIC
;
}
while
(
vlc_object_alive
(
p_demux
)
)
{
frame_header_t
fh
;
int64_t
i_tell
;
if
(
(
i_tell
=
stream_Tell
(
p_demux
->
s
)
)
>=
i_pos
)
else
if
(
(
i_pos
=
p_sys
->
i_first_frame_offset
+
(
stream_Size
(
p_demux
->
s
)
-
p_sys
->
i_first_frame_offset
)
*
f
)
>=
0
)
break
;
return
ControlSetPosition
(
p_demux
,
i_pos
,
true
)
;
if
(
FrameHeaderLoad
(
p_demux
,
&
fh
)
)
else
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
if
(
fh
.
i_type
==
'A'
||
fh
.
i_type
==
'V'
)
demux_IndexAppend
(
&
p_sys
->
idx
,(
int64_t
)
fh
.
i_timecode
*
1000
,
i_tell
);
if
(
fh
.
i_type
!=
'R'
)
stream_Read
(
p_demux
->
s
,
NULL
,
fh
.
i_length
);
}
return
VLC_SUCCESS
;
}
}
case
DEMUX_GET_TIME
:
case
DEMUX_GET_TIME
:
pi64
=
(
int64_t
*
)
va_arg
(
args
,
int64_t
*
);
pi64
=
(
int64_t
*
)
va_arg
(
args
,
int64_t
*
);
*
pi64
=
p_sys
->
i_pcr
>=
0
?
p_sys
->
i_pcr
:
0
;
*
pi64
=
p_sys
->
i_pcr
>=
0
?
p_sys
->
i_pcr
:
0
;
...
@@ -473,52 +498,97 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
...
@@ -473,52 +498,97 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
int64_t
i_pos
;
int64_t
i_pos
;
i64
=
(
int64_t
)
va_arg
(
args
,
int64_t
);
i64
=
(
int64_t
)
va_arg
(
args
,
int64_t
);
p_sys
->
i_pcr
=
-
1
;
i_pos
=
demux_IndexConvertTime
(
&
p_sys
->
idx
,
i64
);
i_pos
=
demux_IndexConvertTime
(
&
p_sys
->
idx
,
i64
);
if
(
i_pos
<
0
)
return
VLC_EGENERIC
;
else
return
ControlSetPosition
(
p_demux
,
i_pos
,
false
);
}
case
DEMUX_GET_LENGTH
:
pi64
=
(
int64_t
*
)
va_arg
(
args
,
int64_t
*
);
if
(
p_sys
->
i_total_length
>=
0
)
{
*
pi64
=
p_sys
->
i_total_length
;
return
VLC_SUCCESS
;
}
else
if
(
stream_Tell
(
p_demux
->
s
)
>
p_sys
->
i_first_frame_offset
)
{
/* This should give an approximation of the total duration */
*
pi64
=
(
double
)(
stream_Size
(
p_demux
->
s
)
-
p_sys
->
i_first_frame_offset
)
/
(
double
)(
stream_Tell
(
p_demux
->
s
)
-
p_sys
->
i_first_frame_offset
)
*
(
double
)(
p_sys
->
i_pcr
>=
0
?
p_sys
->
i_pcr
:
0
);
return
VLC_SUCCESS
;
}
else
return
VLC_EGENERIC
;
case
DEMUX_GET_FPS
:
pf
=
(
double
*
)
va_arg
(
args
,
double
*
);
*
pf
=
p_sys
->
hdr
.
d_fps
;
return
VLC_SUCCESS
;
case
DEMUX_GET_META
:
default:
return
VLC_EGENERIC
;
}
}
static
int
ControlSetPosition
(
demux_t
*
p_demux
,
int64_t
i_pos
,
bool
b_guess
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
if
(
i_pos
<
0
)
if
(
i_pos
<
0
)
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
/* if we can seek in the stream */
if
(
p_sys
->
b_seekable
&&
!
b_guess
)
{
if
(
stream_Seek
(
p_demux
->
s
,
i_pos
)
)
if
(
stream_Seek
(
p_demux
->
s
,
i_pos
)
)
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
else
{
/* forward seek */
if
(
i_pos
>
stream_Tell
(
p_demux
->
s
)
)
{
msg_Dbg
(
p_demux
,
"unable to seek, skipping frames (slow)"
);
}
else
{
msg_Warn
(
p_demux
,
"unable to seek, only forward seeking is possible"
);
p_sys
->
i_pcr
=
-
1
;
return
VLC_EGENERIC
;
}
}
while
(
vlc_object_alive
(
p_demux
)
)
while
(
vlc_object_alive
(
p_demux
)
)
{
{
frame_header_t
fh
;
frame_header_t
fh
;
int64_t
i_tell
;
if
(
(
i_tell
=
stream_Tell
(
p_demux
->
s
)
)
>=
i_pos
)
break
;
if
(
FrameHeaderLoad
(
p_demux
,
&
fh
)
)
if
(
FrameHeaderLoad
(
p_demux
,
&
fh
)
)
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
if
(
fh
.
i_type
==
'A'
||
fh
.
i_type
==
'V'
)
if
(
fh
.
i_type
==
'A'
||
fh
.
i_type
==
'V'
)
{
{
int64_t
i_time
=
(
int64_t
)
fh
.
i_timecode
*
1000
;
if
(
!
fh
.
i_keyframe
&&
!
p_sys
->
b_index
)
int64_t
i_tell
=
stream_Tell
(
p_demux
->
s
)
-
12
;
demux_IndexAppend
(
&
p_sys
->
idx
,(
int64_t
)
fh
.
i_timecode
*
1000
,
i_tell
);
demux_IndexAppend
(
&
p_sys
->
idx
,
i_time
,
i_tell
);
if
(
i_time
>=
i64
)
return
stream_Seek
(
p_demux
->
s
,
i_tell
);
}
if
(
fh
.
i_type
!=
'R'
)
stream_Read
(
p_demux
->
s
,
NULL
,
fh
.
i_length
);
}
return
VLC_SUCCESS
;
}
}
case
DEMUX_GET_LENGTH
:
if
(
fh
.
i_type
!=
'R'
&&
fh
.
i_length
>
0
)
pi64
=
(
int64_t
*
)
va_arg
(
args
,
int64_t
*
);
{
if
(
stream_Read
(
p_demux
->
s
,
NULL
,
fh
.
i_length
)
!=
fh
.
i_length
)
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
case
DEMUX_GET_FPS
:
pf
=
(
double
*
)
va_arg
(
args
,
double
*
);
*
pf
=
p_sys
->
hdr
.
d_fps
;
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
case
DEMUX_GET_META
:
default:
return
VLC_EGENERIC
;
}
}
}
/*****************************************************************************
/*****************************************************************************
...
@@ -573,7 +643,7 @@ static int HeaderLoad( demux_t *p_demux, header_t *h )
...
@@ -573,7 +643,7 @@ static int HeaderLoad( demux_t *p_demux, header_t *h )
*/
*/
static
int
FrameHeaderLoad
(
demux_t
*
p_demux
,
frame_header_t
*
h
)
static
int
FrameHeaderLoad
(
demux_t
*
p_demux
,
frame_header_t
*
h
)
{
{
uint8_t
buffer
[
12
]
;
uint8_t
*
buffer
=
p_demux
->
p_sys
->
fh_buffer
;
if
(
stream_Read
(
p_demux
->
s
,
buffer
,
12
)
!=
12
)
if
(
stream_Read
(
p_demux
->
s
,
buffer
,
12
)
!=
12
)
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
...
@@ -618,22 +688,180 @@ static int ExtendedHeaderLoad( demux_t *p_demux, extended_header_t *h )
...
@@ -618,22 +688,180 @@ static int ExtendedHeaderLoad( demux_t *p_demux, extended_header_t *h )
h
->
i_lavc_qmin
=
GetDWLE
(
&
buffer
[
48
]
);
h
->
i_lavc_qmin
=
GetDWLE
(
&
buffer
[
48
]
);
h
->
i_lavc_qmin
=
GetDWLE
(
&
buffer
[
52
]
);
h
->
i_lavc_qmin
=
GetDWLE
(
&
buffer
[
52
]
);
h
->
i_lavc_maxqdiff
=
GetDWLE
(
&
buffer
[
56
]
);
h
->
i_lavc_maxqdiff
=
GetDWLE
(
&
buffer
[
56
]
);
h
->
i_seekable_offset
=
GetQWLE
(
&
buffer
[
60
]
);
h
->
i_seek
t
able_offset
=
GetQWLE
(
&
buffer
[
60
]
);
h
->
i_keyframe_adjust_offset
=
GetQWLE
(
&
buffer
[
68
]
);
h
->
i_keyframe_adjust_offset
=
GetQWLE
(
&
buffer
[
68
]
);
#if 0
#if 0
msg_Dbg( p_demux, "ex hdr: v=%d vffc=%4.4s afcc=%4.4s %dHz %dbits ach=%d acr=%d aq=%d"
msg_Dbg( p_demux, "ex hdr: v=%d vffc=%4.4s afcc=%4.4s %dHz %dbits ach=%d acr=%d aq=%d"
"rtjpeg q=%d lf=%d lc=%d lavc br=%d qmin=%d qmax=%d maxqdiff=%d seekableoff=%
lld keyfao=%lld"
,
"rtjpeg q=%d lf=%d lc=%d lavc br=%d qmin=%d qmax=%d maxqdiff=%d seekableoff=%
"PRIi64" keyfao=%"PRIi64
,
h->i_version,
h->i_version,
(char*)&h->i_video_fcc,
(char*)&h->i_video_fcc,
(char*)&h->i_audio_fcc, h->i_audio_sample_rate, h->i_audio_bits_per_sample, h->i_audio_channels,
(char*)&h->i_audio_fcc, h->i_audio_sample_rate, h->i_audio_bits_per_sample, h->i_audio_channels,
h->i_audio_compression_ratio, h->i_audio_quality,
h->i_audio_compression_ratio, h->i_audio_quality,
h->i_rtjpeg_quality, h->i_rtjpeg_luma_filter, h->i_rtjpeg_chroma_filter,
h->i_rtjpeg_quality, h->i_rtjpeg_luma_filter, h->i_rtjpeg_chroma_filter,
h->i_lavc_bitrate, h->i_lavc_qmin, h->i_lavc_qmax, h->i_lavc_maxqdiff,
h->i_lavc_bitrate, h->i_lavc_qmin, h->i_lavc_qmax, h->i_lavc_maxqdiff,
h->i_seekable_offset, h->i_keyframe_adjust_offset );
h->i_seek
t
able_offset, h->i_keyframe_adjust_offset );
#endif
#endif
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
/*
typedef struct
{
int64_t i_file_offset;
int32_t i_keyframe_number;
} seektable_entry_t;
typedef struct
{
int32_t i_adjust;
int32_t i_keyframe_number;
} kfatable_entry_t;
*/
static
int
SeekTableLoad
(
demux_t
*
p_demux
,
demux_sys_t
*
p_sys
)
{
frame_header_t
fh
;
int64_t
i_original_pos
;
uint8_t
*
p_seek_table
;
uint8_t
*
p_kfa_table
;
int32_t
i_seek_elements
=
0
,
i_kfa_elements
=
0
,
j
;
int64_t
i_time
,
i_offset
;
int
keyframe
,
last_keyframe
=
0
,
frame
=
0
,
kfa_entry_id
=
0
;
if
(
p_sys
->
exh
.
i_seektable_offset
<=
0
)
return
VLC_SUCCESS
;
/* Save current position */
i_original_pos
=
stream_Tell
(
p_demux
->
s
);
#if 0
msg_Dbg( p_demux, "current offset %"PRIi64, i_original_pos );
msg_Dbg( p_demux, "seeking in stream to %"PRIi64, p_sys->exh.i_seektable_offset );
#endif
if
(
stream_Seek
(
p_demux
->
s
,
p_sys
->
exh
.
i_seektable_offset
)
)
return
VLC_EGENERIC
;
if
(
FrameHeaderLoad
(
p_demux
,
&
fh
)
)
return
VLC_EGENERIC
;
if
(
fh
.
i_type
==
'Q'
)
{
p_seek_table
=
malloc
(
fh
.
i_length
);
if
(
p_seek_table
==
NULL
)
return
VLC_ENOMEM
;
if
(
stream_Read
(
p_demux
->
s
,
p_seek_table
,
fh
.
i_length
)
!=
fh
.
i_length
)
{
free
(
p_seek_table
);
return
VLC_EGENERIC
;
}
i_seek_elements
=
fh
.
i_length
/
12
;
}
else
{
msg_Warn
(
p_demux
,
"invalid seektable, frame type=%c"
,
fh
.
i_type
);
stream_Seek
(
p_demux
->
s
,
i_original_pos
);
return
VLC_EGENERIC
;
}
/* Get keyframe adjust offsets */
if
(
p_sys
->
exh
.
i_keyframe_adjust_offset
>
0
)
{
msg_Dbg
(
p_demux
,
"seeking in stream to %"
PRIi64
,
p_sys
->
exh
.
i_keyframe_adjust_offset
);
if
(
stream_Seek
(
p_demux
->
s
,
p_sys
->
exh
.
i_keyframe_adjust_offset
)
)
{
free
(
p_seek_table
);
return
VLC_EGENERIC
;
}
if
(
FrameHeaderLoad
(
p_demux
,
&
fh
)
)
{
free
(
p_seek_table
);
return
VLC_EGENERIC
;
}
if
(
fh
.
i_type
==
'K'
&&
fh
.
i_length
>=
8
)
{
p_kfa_table
=
malloc
(
fh
.
i_length
);
if
(
p_seek_table
==
NULL
)
{
free
(
p_seek_table
);
return
VLC_ENOMEM
;
}
if
(
stream_Read
(
p_demux
->
s
,
p_kfa_table
,
fh
.
i_length
)
!=
fh
.
i_length
)
{
free
(
p_seek_table
);
free
(
p_kfa_table
);
return
VLC_EGENERIC
;
}
i_kfa_elements
=
fh
.
i_length
/
8
;
}
}
if
(
i_kfa_elements
>
0
)
msg_Warn
(
p_demux
,
"untested keyframe adjust support, upload samples"
);
for
(
j
=
0
;
j
<
i_seek_elements
;
j
++
)
{
#if 0
uint8_t* p = p_seek_table + j * 12;
msg_Dbg( p_demux, "%x %x %x %x %x %x %x %x %x %x %x %x",
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11]);
#endif
keyframe
=
GetDWLE
(
p_seek_table
+
j
*
12
+
8
);
frame
+=
(
keyframe
-
last_keyframe
)
*
p_sys
->
hdr
.
i_keyframe_distance
;
if
(
kfa_entry_id
<
i_kfa_elements
&&
*
(
int32_t
*
)(
p_kfa_table
+
kfa_entry_id
*
12
+
4
)
==
j
)
{
frame
-=
*
(
int32_t
*
)(
p_kfa_table
+
kfa_entry_id
*
12
);
msg_Dbg
(
p_demux
,
"corrected keyframe %d with current frame number %d (corrected with %d)"
,
keyframe
,
frame
,
*
(
int32_t
*
)(
p_kfa_table
+
kfa_entry_id
*
12
)
);
kfa_entry_id
++
;
}
i_time
=
(
double
)(
(
int64_t
)
frame
*
1000000
)
/
p_sys
->
hdr
.
d_fps
;
i_offset
=
GetQWLE
(
p_seek_table
+
j
*
12
);
if
(
i_offset
==
0
&&
i_time
!=
0
)
msg_Dbg
(
p_demux
,
"invalid file offset %d %"
PRIi64
,
keyframe
,
i_offset
);
else
{
demux_IndexAppend
(
&
p_sys
->
idx
,
i_time
,
i_offset
);
#if 0
msg_Dbg( p_demux, "adding entry position %d %"PRIi64 " file offset %"PRIi64, keyframe, i_time, i_offset );
#endif
}
last_keyframe
=
keyframe
;
}
p_sys
->
i_total_frames
=
(
int64_t
)
frame
;
p_sys
->
b_index
=
true
;
p_sys
->
i_total_length
=
p_sys
->
i_total_frames
*
1000000
/
p_sys
->
hdr
.
d_fps
;
msg_Dbg
(
p_demux
,
"index table loaded (%d elements)"
,
i_seek_elements
);
if
(
i_kfa_elements
)
free
(
p_kfa_table
);
free
(
p_seek_table
);
/* Restore stream position */
if
(
stream_Seek
(
p_demux
->
s
,
i_original_pos
)
)
return
VLC_EGENERIC
;
return
VLC_SUCCESS
;
}
/*****************************************************************************/
/*****************************************************************************/
#define DEMUX_INDEX_SIZE_MAX (100000)
#define DEMUX_INDEX_SIZE_MAX (100000)
static
void
demux_IndexInit
(
demux_index_t
*
p_idx
)
static
void
demux_IndexInit
(
demux_index_t
*
p_idx
)
...
@@ -778,3 +1006,4 @@ static int64_t demux_IndexFindOffset( demux_index_t *p_idx, int64_t i_offset )
...
@@ -778,3 +1006,4 @@ static int64_t demux_IndexFindOffset( demux_index_t *p_idx, int64_t i_offset )
else
else
return
p_idx
->
idx
[
i_max
].
i_offset
;
return
p_idx
->
idx
[
i_max
].
i_offset
;
}
}
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