Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
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
Commits
a00addff
Commit
a00addff
authored
Jun 24, 2003
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* mkv: clean up, more input infos, begin to parse Tags element (don't work
yet).
parent
80e0bf5c
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
881 additions
and
600 deletions
+881
-600
modules/demux/mkv.cpp
modules/demux/mkv.cpp
+881
-600
No files found.
modules/demux/mkv.cpp
View file @
a00addff
...
...
@@ -2,7 +2,7 @@
* mkv.cpp : matroska demuxer
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: mkv.cpp,v 1.
8 2003/06/24 06:07:14
fenrir Exp $
* $Id: mkv.cpp,v 1.
9 2003/06/24 18:42:50
fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
...
...
@@ -28,6 +28,10 @@
#include <vlc/vlc.h>
#ifdef HAVE_TIME_H
# include <time.h>
/* time() */
#endif
#include <vlc/input.h>
#include <codecs.h>
/* BITMAPINFOHEADER, WAVEFORMATEX */
...
...
@@ -35,6 +39,7 @@
#include <iostream>
#include <cassert>
#include <typeinfo>
#include <wchar.h>
/* libebml and matroska */
#include "ebml/EbmlHead.h"
...
...
@@ -59,6 +64,8 @@
#include "matroska/KaxSeekHead.h"
#include "matroska/KaxSegment.h"
#include "matroska/KaxTag.h"
#include "matroska/KaxTags.h"
#include "matroska/KaxTagMulti.h"
#include "matroska/KaxTracks.h"
#include "matroska/KaxTrackAudio.h"
#include "matroska/KaxTrackVideo.h"
...
...
@@ -80,10 +87,12 @@ static int Demux ( input_thread_t * );
* Module descriptor
*****************************************************************************/
vlc_module_begin
();
#if 0
add_category_hint( N_("mkv-demuxer"), NULL, VLC_TRUE );
add_bool( "mkv-index", 0, NULL,
N_("Create index if no cues found"),
N_("Create index if no cues found"), VLC_TRUE );
#endif
set_description
(
_
(
"mka/mkv stream demuxer"
)
);
set_capability
(
"demux"
,
50
);
set_callbacks
(
Activate
,
Deactivate
);
...
...
@@ -99,6 +108,7 @@ class vlc_stream_io_callback: public IOCallback
{
private:
input_thread_t
*
p_input
;
vlc_bool_t
mb_eof
;
public:
vlc_stream_io_callback
(
input_thread_t
*
);
...
...
@@ -110,448 +120,184 @@ class vlc_stream_io_callback: public IOCallback
virtual
void
close
(
void
);
};
vlc_stream_io_callback
::
vlc_stream_io_callback
(
input_thread_t
*
p_input_
)
{
p_input
=
p_input_
;
}
uint32_t
vlc_stream_io_callback
::
read
(
void
*
p_buffer
,
size_t
i_size
)
/*****************************************************************************
* Ebml Stream parser
*****************************************************************************/
class
EbmlParser
{
data_packet_t
*
p_data
;
public:
EbmlParser
(
EbmlStream
*
es
,
EbmlElement
*
el_start
);
~
EbmlParser
(
void
);
int
i_count
;
int
i_read
=
0
;
void
Up
(
void
);
void
Down
(
void
);
EbmlElement
*
Get
(
void
);
void
Keep
(
void
);
int
GetLevel
(
void
);
if
(
!
i_size
)
{
return
0
;
}
private:
EbmlStream
*
m_es
;
int
mi_level
;
EbmlElement
*
m_el
[
6
];
do
{
i_count
=
input_SplitBuffer
(
p_input
,
&
p_data
,
__MIN
(
i_size
,
10240
)
);
if
(
i_count
<=
0
)
{
return
i_read
;
}
memcpy
(
p_buffer
,
p_data
->
p_payload_start
,
i_count
);
input_DeletePacket
(
p_input
->
p_method_data
,
p_data
);
EbmlElement
*
m_got
;
(
uint8_t
*
)
p_buffer
+=
i_count
;
i_size
-=
i_count
;
i_read
+=
i_count
;
int
mi_user_level
;
vlc_bool_t
mb_keep
;
}
;
}
while
(
i_size
);
return
i_read
;
/*****************************************************************************
* Some functions to manipulate memory
*****************************************************************************/
#define GetWLE( p ) __GetWLE( (uint8_t*)p )
#define GetDWLE( p ) __GetDWLE( (uint8_t*)p )
#define GetFOURCC( p ) __GetFOURCC( (uint8_t*)p )
static
uint16_t
__GetWLE
(
uint8_t
*
p
)
{
return
(
uint16_t
)
p
[
0
]
|
(
((
uint16_t
)
p
[
1
])
<<
8
);
}
static
uint32_t
__GetDWLE
(
uint8_t
*
p
)
{
return
(
uint32_t
)
p
[
0
]
|
(
((
uint32_t
)
p
[
1
])
<<
8
)
|
(
((
uint32_t
)
p
[
2
])
<<
16
)
|
(
((
uint32_t
)
p
[
3
])
<<
24
);
}
static
vlc_fourcc_t
__GetFOURCC
(
uint8_t
*
p
)
{
return
VLC_FOURCC
(
p
[
0
],
p
[
1
],
p
[
2
],
p
[
3
]
);
}
void
vlc_stream_io_callback
::
setFilePointer
(
int64_t
i_offset
,
seek_mode
mode
)
/*****************************************************************************
* definitions of structures and functions used by this plugins
*****************************************************************************/
typedef
struct
{
int64_t
i_pos
;
int64_t
i_last
;
int
i_cat
;
vlc_bool_t
b_default
;
int
i_number
;
i_last
=
getFilePointer
();
int
i_extra_data
;
uint8_t
*
p_extra_data
;
vlc_mutex_lock
(
&
p_input
->
stream
.
stream_lock
);
switch
(
mode
)
{
case
seek_beginning
:
i_pos
=
i_offset
;
break
;
case
seek_end
:
i_pos
=
p_input
->
stream
.
p_selected_area
->
i_size
-
i_offset
;
break
;
default:
i_pos
=
i_last
+
i_offset
;
break
;
}
char
*
psz_language
;
if
(
i_pos
<
0
||
(
i_pos
>
p_input
->
stream
.
p_selected_area
->
i_size
&&
p_input
->
stream
.
p_selected_area
->
i_size
!=
0
)
)
{
msg_Err
(
p_input
,
"seeking to wrong place (i_pos=%lld)"
,
i_pos
);
vlc_mutex_unlock
(
&
p_input
->
stream
.
stream_lock
);
return
;
}
vlc_mutex_unlock
(
&
p_input
->
stream
.
stream_lock
);
char
*
psz_codec
;
vlc_fourcc_t
i_codec
;
if
(
i_pos
==
i_last
)
{
return
;
}
uint64_t
i_default_duration
;
/* video */
int
i_width
;
int
i_height
;
int
i_display_width
;
int
i_display_height
;
float
f_fps
;
msg_Dbg
(
p_input
,
"####################seek new=%lld old=%lld"
,
i_pos
,
getFilePointer
()
);
if
(
p_input
->
stream
.
b_seekable
&&
(
/*p_input->stream.i_method == INPUT_METHOD_FILE ||*/
i_pos
<
i_last
||
i_pos
-
i_last
>
p_input
->
i_bufsize
/
4
)
)
{
input_AccessReinit
(
p_input
);
p_input
->
pf_seek
(
p_input
,
i_pos
);
}
else
if
(
i_pos
>
i_last
)
{
data_packet_t
*
p_data
;
int
i_skip
=
i_pos
-
i_last
;
/* audio */
int
i_channels
;
int
i_samplerate
;
int
i_bitspersample
;
if
(
i_skip
>
1024
)
{
msg_Warn
(
p_input
,
"will skip %d bytes, slow"
,
i_skip
);
}
es_descriptor_t
*
p_es
;
while
(
i_skip
>
0
)
{
int
i_read
;
i_read
=
input_SplitBuffer
(
p_input
,
&
p_data
,
__MIN
(
4096
,
i_skip
)
);
if
(
i_read
<
0
)
{
msg_Err
(
p_input
,
"seek failed"
);
return
;
}
i_skip
-=
i_read
;
input_DeletePacket
(
p_input
->
p_method_data
,
p_data
);
if
(
i_read
==
0
&&
i_skip
>
0
)
{
msg_Err
(
p_input
,
"seek failed"
);
return
;
}
}
}
else
{
msg_Err
(
p_input
,
"cannot seek or emulate seek to %lld from %lld"
,
i_pos
,
i_last
);
}
}
vlc_bool_t
b_inited
;
/* data to be send first */
int
i_data_init
;
uint8_t
*
p_data_init
;
size_t
vlc_stream_io_callback
::
write
(
const
void
*
p_buffer
,
size_t
i_size
)
{
return
0
;
}
/* hack : it's for seek */
vlc_bool_t
b_search_keyframe
;
}
mkv_track_t
;
uint64_t
vlc_stream_io_callback
::
getFilePointer
(
void
)
typedef
struct
{
uint64_t
i_pos
;
vlc_mutex_lock
(
&
p_input
->
stream
.
stream_lock
);
i_pos
=
p_input
->
stream
.
p_selected_area
->
i_tell
;
vlc_mutex_unlock
(
&
p_input
->
stream
.
stream_lock
);
int
i_track
;
int
i_block_number
;
return
i_pos
;
}
int64_t
i_position
;
int64_t
i_time
;
void
vlc_stream_io_callback
::
close
(
void
)
{
return
;
}
vlc_bool_t
b_key
;
}
mkv_index_t
;
/*****************************************************************************
* Ebml Stream parser
*****************************************************************************/
class
EbmlParser
struct
demux_sys_t
{
public:
EbmlParser
(
EbmlStream
*
es
,
EbmlElement
*
el_start
)
;
~
EbmlParser
(
void
)
;
vlc_stream_io_callback
*
in
;
EbmlStream
*
es
;
EbmlParser
*
ep
;
int
SetNext
(
const
EbmlCallbacks
&
ClassInfos
);
/* time scale */
uint64_t
i_timescale
;
void
Up
(
void
);
void
Down
(
void
);
EbmlElement
*
Get
(
void
);
void
Keep
(
void
);
/* duration of the segment */
float
f_duration
;
int
GetLevel
(
void
);
/* all tracks */
int
i_track
;
mkv_track_t
*
track
;
private:
/* from seekhead */
int64_t
i_cues_position
;
int64_t
i_chapters_position
;
int64_t
i_tags_position
;
EbmlStream
*
m_es
;
int
mi_level
;
EbmlElement
*
m_el
[
6
]
;
/* current data */
KaxSegment
*
segment
;
KaxCluster
*
cluster
;
EbmlElement
*
m_got
;
mtime_t
i_pts
;
int
mi_user_level
;
vlc_bool_t
mb_keep
;
vlc_bool_t
b_cues
;
int
i_index
;
int
i_index_max
;
mkv_index_t
*
index
;
/* info */
char
*
psz_muxing_application
;
char
*
psz_writing_application
;
char
*
psz_segment_filename
;
char
*
psz_title
;
char
*
psz_date_utc
;
};
EbmlParser
::
EbmlParser
(
EbmlStream
*
es
,
EbmlElement
*
el_start
)
#define MKVD_TIMECODESCALE 1000000
static
void
IndexAppendCluster
(
input_thread_t
*
p_input
,
KaxCluster
*
cluster
);
static
char
*
UTF8ToStr
(
const
UTFstring
&
u
);
static
void
LoadCues
(
input_thread_t
*
);
static
void
InformationsCreate
(
input_thread_t
*
p_input
);
/*****************************************************************************
* Activate: initializes matroska demux structures
*****************************************************************************/
static
int
Activate
(
vlc_object_t
*
p_this
)
{
int
i
;
input_thread_t
*
p_input
=
(
input_thread_t
*
)
p_this
;
demux_sys_t
*
p_sys
;
uint8_t
*
p_peek
;
m_es
=
es
;
m_got
=
NULL
;
m_el
[
0
]
=
el_start
;
int
i_track
;
vlc_bool_t
b_audio_selected
;
int
i_spu_channel
,
i_audio_channel
;
for
(
i
=
1
;
i
<
6
;
i
++
)
EbmlElement
*
el
=
NULL
,
*
el1
=
NULL
,
*
el2
=
NULL
,
*
el3
=
NULL
,
*
el4
=
NULL
;
/* Initialize access plug-in structures. */
if
(
p_input
->
i_mtu
==
0
)
{
m_el
[
i
]
=
NULL
;
/* Improve speed. */
p_input
->
i_bufsize
=
INPUT_DEFAULT_BUFSIZE
;
}
mi_level
=
1
;
mi_user_level
=
1
;
mb_keep
=
VLC_FALSE
;
}
EbmlParser
::~
EbmlParser
(
void
)
{
int
i
;
/* Set the demux function */
p_input
->
pf_demux
=
Demux
;
for
(
i
=
1
;
i
<
mi_level
;
i
++
)
{
if
(
!
mb_keep
)
{
delete
m_el
[
i
];
}
mb_keep
=
VLC_FALSE
;
}
}
void
EbmlParser
::
Up
(
void
)
{
if
(
mi_user_level
==
mi_level
)
{
fprintf
(
stderr
,
" arrrrrrrrrrrrrg Up cannot escape itself
\n
"
);
}
mi_user_level
--
;
}
void
EbmlParser
::
Down
(
void
)
{
mi_user_level
++
;
mi_level
++
;
}
void
EbmlParser
::
Keep
(
void
)
{
mb_keep
=
VLC_TRUE
;
}
int
EbmlParser
::
GetLevel
(
void
)
{
return
mi_user_level
;
}
EbmlElement
*
EbmlParser
::
Get
(
void
)
{
int
i_ulev
=
0
;
if
(
mi_user_level
!=
mi_level
)
{
return
NULL
;
}
if
(
m_got
)
{
EbmlElement
*
ret
=
m_got
;
m_got
=
NULL
;
return
ret
;
}
if
(
m_el
[
mi_level
]
)
{
m_el
[
mi_level
]
->
SkipData
(
*
m_es
,
m_el
[
mi_level
]
->
Generic
().
Context
);
if
(
!
mb_keep
)
{
delete
m_el
[
mi_level
];
}
mb_keep
=
VLC_FALSE
;
}
m_el
[
mi_level
]
=
m_es
->
FindNextElement
(
m_el
[
mi_level
-
1
]
->
Generic
().
Context
,
i_ulev
,
0xFFFFFFFFL
,
true
,
1
);
if
(
i_ulev
>
0
)
{
while
(
i_ulev
>
0
)
{
if
(
mi_level
==
1
)
{
mi_level
=
0
;
return
NULL
;
}
delete
m_el
[
mi_level
-
1
];
m_got
=
m_el
[
mi_level
-
1
]
=
m_el
[
mi_level
];
m_el
[
mi_level
]
=
NULL
;
mi_level
--
;
i_ulev
--
;
}
return
NULL
;
}
else
if
(
m_el
[
mi_level
]
==
NULL
)
{
fprintf
(
stderr
,
" m_el[mi_level] == NULL
\n
"
);
}
return
m_el
[
mi_level
];
}
/*****************************************************************************
* Some functions to manipulate memory
*****************************************************************************/
#define GetWLE( p ) __GetWLE( (uint8_t*)p )
#define GetDWLE( p ) __GetDWLE( (uint8_t*)p )
#define GetFOURCC( p ) __GetFOURCC( (uint8_t*)p )
static
uint16_t
__GetWLE
(
uint8_t
*
p
)
{
return
(
uint16_t
)
p
[
0
]
|
(
((
uint16_t
)
p
[
1
])
<<
8
);
}
static
uint32_t
__GetDWLE
(
uint8_t
*
p
)
{
return
(
uint32_t
)
p
[
0
]
|
(
((
uint32_t
)
p
[
1
])
<<
8
)
|
(
((
uint32_t
)
p
[
2
])
<<
16
)
|
(
((
uint32_t
)
p
[
3
])
<<
24
);
}
static
vlc_fourcc_t
__GetFOURCC
(
uint8_t
*
p
)
{
return
VLC_FOURCC
(
p
[
0
],
p
[
1
],
p
[
2
],
p
[
3
]
);
}
/*****************************************************************************
* definitions of structures and functions used by this plugins
*****************************************************************************/
typedef
struct
{
int
i_cat
;
vlc_bool_t
b_default
;
int
i_number
;
int
i_extra_data
;
uint8_t
*
p_extra_data
;
char
*
psz_language
;
char
*
psz_codec
;
vlc_fourcc_t
i_codec
;
uint64_t
i_default_duration
;
/* video */
int
i_width
;
int
i_height
;
int
i_display_width
;
int
i_display_height
;
float
f_fps
;
/* audio */
int
i_channels
;
int
i_samplerate
;
int
i_bitspersample
;
es_descriptor_t
*
p_es
;
vlc_bool_t
b_inited
;
/* data to be send first */
int
i_data_init
;
uint8_t
*
p_data_init
;
/* hack : it's for seek */
vlc_bool_t
b_search_keyframe
;
}
mkv_track_t
;
typedef
struct
{
int
i_track
;
int
i_block_number
;
int64_t
i_position
;
int64_t
i_time
;
vlc_bool_t
b_key
;
}
mkv_index_t
;
struct
demux_sys_t
{
vlc_stream_io_callback
*
in
;
EbmlStream
*
es
;
EbmlParser
*
ep
;
/* time scale */
uint64_t
i_timescale
;
/* duration of the segment */
float
f_duration
;
/* all tracks */
int
i_track
;
mkv_track_t
*
track
;
/* from seekhead */
int64_t
i_cues_position
;
int64_t
i_chapters_position
;
/* current data */
KaxSegment
*
segment
;
KaxCluster
*
cluster
;
mtime_t
i_pts
;
vlc_bool_t
b_cues
;
int
i_index
;
int
i_index_max
;
mkv_index_t
*
index
;
};
#define MKVD_TIMECODESCALE 1000000
static
void
IndexAppendCluster
(
input_thread_t
*
p_input
,
KaxCluster
*
cluster
)
{
demux_sys_t
*
p_sys
=
p_input
->
p_demux_data
;
#define idx p_sys->index[p_sys->i_index]
idx
.
i_track
=
-
1
;
idx
.
i_block_number
=
-
1
;
idx
.
i_position
=
cluster
->
GetElementPosition
();
idx
.
i_time
=
-
1
;
idx
.
b_key
=
VLC_TRUE
;
p_sys
->
i_index
++
;
if
(
p_sys
->
i_index
>=
p_sys
->
i_index_max
)
{
p_sys
->
i_index_max
+=
1024
;
p_sys
->
index
=
(
mkv_index_t
*
)
realloc
(
p_sys
->
index
,
sizeof
(
mkv_index_t
)
*
p_sys
->
i_index_max
);
}
#undef idx
}
/*****************************************************************************
* Activate: initializes matroska demux structures
*****************************************************************************/
static
int
Activate
(
vlc_object_t
*
p_this
)
{
input_thread_t
*
p_input
=
(
input_thread_t
*
)
p_this
;
demux_sys_t
*
p_sys
;
uint8_t
*
p_peek
;
int
i_track
;
vlc_bool_t
b_audio_selected
;
int
i_spu_channel
,
i_audio_channel
;
EbmlElement
*
el
=
NULL
,
*
el1
=
NULL
,
*
el2
=
NULL
,
*
el3
=
NULL
,
*
el4
=
NULL
;
input_info_category_t
*
p_cat
;
/* Initialize access plug-in structures. */
if
(
p_input
->
i_mtu
==
0
)
{
/* Improve speed. */
p_input
->
i_bufsize
=
INPUT_DEFAULT_BUFSIZE
;
}
/* Set the demux function */
p_input
->
pf_demux
=
Demux
;
/* peek the begining */
if
(
input_Peek
(
p_input
,
&
p_peek
,
4
)
<
4
)
/* peek the begining */
if
(
input_Peek
(
p_input
,
&
p_peek
,
4
)
<
4
)
{
msg_Warn
(
p_input
,
"cannot peek"
);
return
VLC_EGENERIC
;
...
...
@@ -576,12 +322,19 @@ static int Activate( vlc_object_t * p_this )
p_sys
->
i_pts
=
0
;
p_sys
->
i_cues_position
=
-
1
;
p_sys
->
i_chapters_position
=
-
1
;
p_sys
->
i_tags_position
=
-
1
;
p_sys
->
b_cues
=
VLC_FALSE
;
p_sys
->
i_index
=
0
;
p_sys
->
i_index_max
=
1024
;
p_sys
->
index
=
(
mkv_index_t
*
)
malloc
(
sizeof
(
mkv_index_t
)
*
p_sys
->
i_index_max
);
p_sys
->
psz_muxing_application
=
NULL
;
p_sys
->
psz_writing_application
=
NULL
;
p_sys
->
psz_segment_filename
=
NULL
;
p_sys
->
psz_title
=
NULL
;
p_sys
->
psz_date_utc
=
NULL
;;
if
(
p_sys
->
es
==
NULL
)
{
msg_Err
(
p_input
,
"failed to create EbmlStream"
);
...
...
@@ -641,11 +394,72 @@ static int Activate( vlc_object_t * p_this )
msg_Dbg
(
p_input
,
"| | + Duration=%f"
,
p_sys
->
f_duration
);
}
else
else
if
(
EbmlId
(
*
el2
)
==
KaxMuxingApp
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"| | + Unknow (%s)"
,
typeid
(
*
el2
).
name
()
);
KaxMuxingApp
&
mapp
=
*
(
KaxMuxingApp
*
)
el2
;
mapp
.
ReadData
(
p_sys
->
es
->
I_O
()
);
p_sys
->
psz_muxing_application
=
UTF8ToStr
(
UTFstring
(
mapp
)
);
msg_Dbg
(
p_input
,
"| | + Muxing Application=%s"
,
p_sys
->
psz_muxing_application
);
}
}
else
if
(
EbmlId
(
*
el2
)
==
KaxWritingApp
::
ClassInfos
.
GlobalId
)
{
KaxWritingApp
&
wapp
=
*
(
KaxWritingApp
*
)
el2
;
wapp
.
ReadData
(
p_sys
->
es
->
I_O
()
);
p_sys
->
psz_writing_application
=
UTF8ToStr
(
UTFstring
(
wapp
)
);
msg_Dbg
(
p_input
,
"| | + Wrinting Application=%s"
,
p_sys
->
psz_writing_application
);
}
else
if
(
EbmlId
(
*
el2
)
==
KaxSegmentFilename
::
ClassInfos
.
GlobalId
)
{
KaxSegmentFilename
&
sfn
=
*
(
KaxSegmentFilename
*
)
el2
;
sfn
.
ReadData
(
p_sys
->
es
->
I_O
()
);
p_sys
->
psz_segment_filename
=
UTF8ToStr
(
UTFstring
(
sfn
)
);
msg_Dbg
(
p_input
,
"| | + Segment Filename=%s"
,
p_sys
->
psz_segment_filename
);
}
else
if
(
EbmlId
(
*
el2
)
==
KaxTitle
::
ClassInfos
.
GlobalId
)
{
KaxTitle
&
title
=
*
(
KaxTitle
*
)
el2
;
title
.
ReadData
(
p_sys
->
es
->
I_O
()
);
p_sys
->
psz_title
=
UTF8ToStr
(
UTFstring
(
title
)
);
msg_Dbg
(
p_input
,
"| | + Title=%s"
,
p_sys
->
psz_title
);
}
#ifdef HAVE_TIME_H
else
if
(
EbmlId
(
*
el2
)
==
KaxDateUTC
::
ClassInfos
.
GlobalId
)
{
KaxDateUTC
&
date
=
*
(
KaxDateUTC
*
)
el2
;
time_t
i_date
;
struct
tm
tmres
;
char
buffer
[
256
];
date
.
ReadData
(
p_sys
->
es
->
I_O
()
);
i_date
=
date
.
GetEpochDate
();
memset
(
buffer
,
0
,
256
);
if
(
gmtime_r
(
&
i_date
,
&
tmres
)
&&
asctime_r
(
&
tmres
,
buffer
)
)
{
buffer
[
strlen
(
buffer
)
-
1
]
=
'\0'
;
p_sys
->
psz_date_utc
=
strdup
(
buffer
);
msg_Dbg
(
p_input
,
"| | + Date=%s"
,
p_sys
->
psz_date_utc
);
}
}
#endif
else
{
msg_Dbg
(
p_input
,
"| | + Unknow (%s)"
,
typeid
(
*
el2
).
name
()
);
}
}
p_sys
->
ep
->
Up
();
}
else
if
(
EbmlId
(
*
el1
)
==
KaxTracks
::
ClassInfos
.
GlobalId
)
...
...
@@ -957,6 +771,12 @@ static int Activate( vlc_object_t * p_this )
msg_Dbg
(
p_input
,
"| | | = chapters at %lld"
,
i_pos
);
p_sys
->
i_chapters_position
=
p_sys
->
segment
->
GetGlobalPosition
(
i_pos
);
}
else
if
(
id
==
KaxTags
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"| | | = tags at %lld"
,
i_pos
);
p_sys
->
i_tags_position
=
p_sys
->
segment
->
GetGlobalPosition
(
i_pos
);
}
}
}
else
...
...
@@ -1009,144 +829,10 @@ static int Activate( vlc_object_t * p_this )
msg_Warn
(
p_input
,
"chapters unsupported"
);
}
#if 0
if( p_sys->i_cues_position == -1 && config_GetInt( p_input, "mkv-index" ) != 0 )
{
int64_t i_sav_position = p_sys->in->getFilePointer();
EbmlParser *ep;
/* parse to find cues gathering info on all clusters */
msg_Dbg( p_input, "no cues referenced, looking for one" );
/* ugly but like easier */
p_sys->in->setFilePointer( p_sys->cluster->GetElementPosition(), seek_beginning );
ep = new EbmlParser( p_sys->es, p_sys->segment );
while( ( el = ep->Get() ) != NULL )
{
if( EbmlId( *el ) == KaxCluster::ClassInfos.GlobalId )
{
int64_t i_pos = el->GetElementPosition();
msg_Dbg( p_input, "found a cluster at %lld", i_pos );
}
else if( EbmlId( *el ) == KaxCues::ClassInfos.GlobalId )
{
msg_Dbg( p_input, "found a Cues !" );
}
}
delete ep;
msg_Dbg( p_input, "lookind done." );
p_sys->in->setFilePointer( i_sav_position, seek_beginning );
}
#endif
/* *** Load the cue if found *** */
if
(
p_sys
->
i_cues_position
>=
0
&&
p_input
->
stream
.
b_seekable
)
{
int64_t
i_sav_position
=
p_sys
->
in
->
getFilePointer
();
EbmlParser
*
ep
;
EbmlElement
*
cues
;
msg_Dbg
(
p_input
,
"loading cues"
);
p_sys
->
in
->
setFilePointer
(
p_sys
->
i_cues_position
,
seek_beginning
);
cues
=
p_sys
->
es
->
FindNextID
(
KaxCues
::
ClassInfos
,
0xFFFFFFFFL
);
if
(
cues
==
NULL
)
{
msg_Err
(
p_input
,
"cannot load cues (broken seekhead or file)"
);
}
else
{
ep
=
new
EbmlParser
(
p_sys
->
es
,
cues
);
while
(
(
el
=
ep
->
Get
()
)
!=
NULL
)
{
if
(
EbmlId
(
*
el
)
==
KaxCuePoint
::
ClassInfos
.
GlobalId
)
{
#define idx p_sys->index[p_sys->i_index]
idx
.
i_track
=
-
1
;
idx
.
i_block_number
=
-
1
;
idx
.
i_position
=
-
1
;
idx
.
i_time
=
-
1
;
idx
.
b_key
=
VLC_TRUE
;
ep
->
Down
();
while
(
(
el
=
ep
->
Get
()
)
!=
NULL
)
{
if
(
EbmlId
(
*
el
)
==
KaxCueTime
::
ClassInfos
.
GlobalId
)
{
KaxCueTime
&
ctime
=
*
(
KaxCueTime
*
)
el
;
ctime
.
ReadData
(
p_sys
->
es
->
I_O
()
);
idx
.
i_time
=
uint64
(
ctime
)
*
(
mtime_t
)
1000000000
/
p_sys
->
i_timescale
;
}
else
if
(
EbmlId
(
*
el
)
==
KaxCueTrackPositions
::
ClassInfos
.
GlobalId
)
{
ep
->
Down
();
while
(
(
el
=
ep
->
Get
()
)
!=
NULL
)
{
if
(
EbmlId
(
*
el
)
==
KaxCueTrack
::
ClassInfos
.
GlobalId
)
{
KaxCueTrack
&
ctrack
=
*
(
KaxCueTrack
*
)
el
;
ctrack
.
ReadData
(
p_sys
->
es
->
I_O
()
);
idx
.
i_track
=
uint16
(
ctrack
);
}
else
if
(
EbmlId
(
*
el
)
==
KaxCueClusterPosition
::
ClassInfos
.
GlobalId
)
{
KaxCueClusterPosition
&
ccpos
=
*
(
KaxCueClusterPosition
*
)
el
;
ccpos
.
ReadData
(
p_sys
->
es
->
I_O
()
);
idx
.
i_position
=
p_sys
->
segment
->
GetGlobalPosition
(
uint64
(
ccpos
)
);
}
else
if
(
EbmlId
(
*
el
)
==
KaxCueBlockNumber
::
ClassInfos
.
GlobalId
)
{
KaxCueBlockNumber
&
cbnum
=
*
(
KaxCueBlockNumber
*
)
el
;
cbnum
.
ReadData
(
p_sys
->
es
->
I_O
()
);
idx
.
i_block_number
=
uint32
(
cbnum
);
}
else
{
msg_Dbg
(
p_input
,
" * Unknow (%s)"
,
typeid
(
*
el
).
name
()
);
}
}
ep
->
Up
();
}
else
{
msg_Dbg
(
p_input
,
" * Unknow (%s)"
,
typeid
(
*
el
).
name
()
);
}
}
ep
->
Up
();
msg_Dbg
(
p_input
,
" * added time=%lld pos=%lld track=%d bnum=%d"
,
idx
.
i_time
,
idx
.
i_position
,
idx
.
i_track
,
idx
.
i_block_number
);
p_sys
->
i_index
++
;
if
(
p_sys
->
i_index
>=
p_sys
->
i_index_max
)
{
p_sys
->
i_index_max
+=
1024
;
p_sys
->
index
=
(
mkv_index_t
*
)
realloc
(
p_sys
->
index
,
sizeof
(
mkv_index_t
)
*
p_sys
->
i_index_max
);
}
#undef idx
}
else
{
msg_Dbg
(
p_input
,
" * Unknow (%s)"
,
typeid
(
*
el
).
name
()
);
}
}
delete
ep
;
delete
cues
;
p_sys
->
b_cues
=
VLC_TRUE
;
}
msg_Dbg
(
p_input
,
"loading cues done."
);
p_sys
->
in
->
setFilePointer
(
i_sav_position
,
seek_beginning
);
LoadCues
(
p_input
);
}
if
(
!
p_sys
->
b_cues
||
p_sys
->
i_index
<=
0
)
...
...
@@ -1489,69 +1175,8 @@ static int Activate( vlc_object_t * p_this )
}
/* add informations */
p_cat
=
input_InfoCategory
(
p_input
,
"Matroska"
);
if
(
p_sys
->
f_duration
>
1000.1
)
{
int64_t
i_sec
=
(
int64_t
)
p_sys
->
f_duration
/
1000
;
int
h
,
m
,
s
;
h
=
i_sec
/
3600
;
m
=
(
i_sec
/
60
)
%
60
;
s
=
i_sec
%
60
;
input_AddInfo
(
p_cat
,
_
(
"Duration"
),
"%d:%2.2d:%2.2d"
,
h
,
m
,
s
);
}
input_AddInfo
(
p_cat
,
_
(
"Number of streams"
),
"%d"
,
p_sys
->
i_track
);
for
(
i_track
=
0
;
i_track
<
p_sys
->
i_track
;
i_track
++
)
{
char
psz_cat
[
strlen
(
"Stream "
)
+
10
];
#define tk p_sys->track[i_track]
sprintf
(
psz_cat
,
"Stream %d"
,
i_track
);
p_cat
=
input_InfoCategory
(
p_input
,
psz_cat
);
switch
(
tk
.
i_cat
)
{
case
AUDIO_ES
:
input_AddInfo
(
p_cat
,
_
(
"Type"
),
_
(
"Audio"
)
);
input_AddInfo
(
p_cat
,
_
(
"Codec"
),
"%.4s (%s)"
,
(
char
*
)
&
tk
.
i_codec
,
tk
.
psz_codec
);
if
(
tk
.
i_channels
>
0
)
{
input_AddInfo
(
p_cat
,
_
(
"Channels"
),
"%d"
,
tk
.
i_channels
);
}
if
(
tk
.
i_samplerate
>
0
)
{
input_AddInfo
(
p_cat
,
_
(
"Sample Rate"
),
"%d"
,
tk
.
i_samplerate
);
}
if
(
tk
.
i_bitspersample
)
{
input_AddInfo
(
p_cat
,
_
(
"Bits Per Sample"
),
"%d"
,
tk
.
i_bitspersample
);
}
break
;
case
VIDEO_ES
:
input_AddInfo
(
p_cat
,
_
(
"Type"
),
_
(
"Video"
)
);
input_AddInfo
(
p_cat
,
_
(
"Codec"
),
"%.4s (%s)"
,
(
char
*
)
&
tk
.
i_codec
,
tk
.
psz_codec
);
if
(
tk
.
i_width
>
0
&&
tk
.
i_height
)
{
input_AddInfo
(
p_cat
,
_
(
"Resolution"
),
"%dx%d"
,
tk
.
i_width
,
tk
.
i_height
);
}
if
(
tk
.
i_display_width
>
0
&&
tk
.
i_display_height
)
{
input_AddInfo
(
p_cat
,
_
(
"Display Resolution"
),
"%dx%d"
,
tk
.
i_display_width
,
tk
.
i_display_height
);
}
if
(
tk
.
f_fps
>
0.1
)
{
input_AddInfo
(
p_cat
,
_
(
"Frame Per Second"
),
"%.3f"
,
tk
.
f_fps
);
}
break
;
case
SPU_ES
:
input_AddInfo
(
p_cat
,
_
(
"Type"
),
_
(
"Subtitle"
)
);
input_AddInfo
(
p_cat
,
_
(
"Codec"
),
"%s"
,
tk
.
psz_codec
);
break
;
}
InformationsCreate
(
p_input
);
#undef tk
}
return
VLC_SUCCESS
;
error:
...
...
@@ -1586,6 +1211,15 @@ static void Deactivate( vlc_object_t *p_this )
}
free
(
p_sys
->
track
);
if
(
p_sys
->
psz_writing_application
)
{
free
(
p_sys
->
psz_writing_application
);
}
if
(
p_sys
->
psz_muxing_application
)
{
free
(
p_sys
->
psz_muxing_application
);
}
delete
p_sys
->
ep
;
delete
p_sys
->
es
;
delete
p_sys
->
in
;
...
...
@@ -2051,9 +1685,7 @@ static int Demux( input_thread_t * p_input )
p_input
->
stream
.
p_selected_area
->
i_size
;
}
msg_Dbg
(
p_input
,
"call Seek"
);
Seek
(
p_input
,
i_date
,
i_percent
);
msg_Dbg
(
p_input
,
"Seek end"
);
}
i_start_pts
=
-
1
;
...
...
@@ -2101,3 +1733,652 @@ static int Demux( input_thread_t * p_input )
}
/*****************************************************************************
* Stream managment
*****************************************************************************/
vlc_stream_io_callback
::
vlc_stream_io_callback
(
input_thread_t
*
p_input_
)
{
p_input
=
p_input_
;
mb_eof
=
VLC_FALSE
;
}
uint32_t
vlc_stream_io_callback
::
read
(
void
*
p_buffer
,
size_t
i_size
)
{
data_packet_t
*
p_data
;
int
i_count
;
int
i_read
=
0
;
if
(
!
i_size
||
mb_eof
)
{
return
0
;
}
do
{
i_count
=
input_SplitBuffer
(
p_input
,
&
p_data
,
__MIN
(
i_size
,
10240
)
);
if
(
i_count
<=
0
)
{
return
i_read
;
}
memcpy
(
p_buffer
,
p_data
->
p_payload_start
,
i_count
);
input_DeletePacket
(
p_input
->
p_method_data
,
p_data
);
(
uint8_t
*
)
p_buffer
+=
i_count
;
i_size
-=
i_count
;
i_read
+=
i_count
;
}
while
(
i_size
);
return
i_read
;
}
void
vlc_stream_io_callback
::
setFilePointer
(
int64_t
i_offset
,
seek_mode
mode
)
{
int64_t
i_pos
;
int64_t
i_last
;
i_last
=
getFilePointer
();
vlc_mutex_lock
(
&
p_input
->
stream
.
stream_lock
);
switch
(
mode
)
{
case
seek_beginning
:
i_pos
=
i_offset
;
break
;
case
seek_end
:
i_pos
=
p_input
->
stream
.
p_selected_area
->
i_size
-
i_offset
;
break
;
default:
i_pos
=
i_last
+
i_offset
;
break
;
}
if
(
i_pos
<
0
||
(
i_pos
>
p_input
->
stream
.
p_selected_area
->
i_size
&&
p_input
->
stream
.
p_selected_area
->
i_size
!=
0
)
)
{
msg_Err
(
p_input
,
"seeking to wrong place (i_pos=%lld)"
,
i_pos
);
vlc_mutex_unlock
(
&
p_input
->
stream
.
stream_lock
);
mb_eof
=
VLC_TRUE
;
return
;
}
vlc_mutex_unlock
(
&
p_input
->
stream
.
stream_lock
);
mb_eof
=
VLC_FALSE
;
if
(
i_pos
==
i_last
)
{
return
;
}
msg_Dbg
(
p_input
,
"####################seek new=%lld old=%lld"
,
i_pos
,
getFilePointer
()
);
if
(
p_input
->
stream
.
b_seekable
&&
(
/*p_input->stream.i_method == INPUT_METHOD_FILE ||*/
i_pos
<
i_last
||
i_pos
-
i_last
>
p_input
->
i_bufsize
/
4
)
)
{
input_AccessReinit
(
p_input
);
p_input
->
pf_seek
(
p_input
,
i_pos
);
}
else
if
(
i_pos
>
i_last
)
{
data_packet_t
*
p_data
;
int
i_skip
=
i_pos
-
i_last
;
if
(
i_skip
>
1024
)
{
msg_Warn
(
p_input
,
"will skip %d bytes, slow"
,
i_skip
);
}
while
(
i_skip
>
0
)
{
int
i_read
;
i_read
=
input_SplitBuffer
(
p_input
,
&
p_data
,
__MIN
(
4096
,
i_skip
)
);
if
(
i_read
<
0
)
{
msg_Err
(
p_input
,
"seek failed"
);
mb_eof
=
VLC_TRUE
;
return
;
}
i_skip
-=
i_read
;
input_DeletePacket
(
p_input
->
p_method_data
,
p_data
);
if
(
i_read
==
0
&&
i_skip
>
0
)
{
msg_Err
(
p_input
,
"seek failed"
);
mb_eof
=
VLC_TRUE
;
return
;
}
}
}
else
{
msg_Err
(
p_input
,
"cannot seek or emulate seek to %lld from %lld"
,
i_pos
,
i_last
);
mb_eof
=
VLC_TRUE
;
}
}
size_t
vlc_stream_io_callback
::
write
(
const
void
*
p_buffer
,
size_t
i_size
)
{
return
0
;
}
uint64_t
vlc_stream_io_callback
::
getFilePointer
(
void
)
{
uint64_t
i_pos
;
vlc_mutex_lock
(
&
p_input
->
stream
.
stream_lock
);
i_pos
=
p_input
->
stream
.
p_selected_area
->
i_tell
;
vlc_mutex_unlock
(
&
p_input
->
stream
.
stream_lock
);
return
i_pos
;
}
void
vlc_stream_io_callback
::
close
(
void
)
{
return
;
}
/*****************************************************************************
* Ebml Stream parser
*****************************************************************************/
EbmlParser
::
EbmlParser
(
EbmlStream
*
es
,
EbmlElement
*
el_start
)
{
int
i
;
m_es
=
es
;
m_got
=
NULL
;
m_el
[
0
]
=
el_start
;
for
(
i
=
1
;
i
<
6
;
i
++
)
{
m_el
[
i
]
=
NULL
;
}
mi_level
=
1
;
mi_user_level
=
1
;
mb_keep
=
VLC_FALSE
;
}
EbmlParser
::~
EbmlParser
(
void
)
{
int
i
;
for
(
i
=
1
;
i
<
mi_level
;
i
++
)
{
if
(
!
mb_keep
)
{
delete
m_el
[
i
];
}
mb_keep
=
VLC_FALSE
;
}
}
void
EbmlParser
::
Up
(
void
)
{
if
(
mi_user_level
==
mi_level
)
{
fprintf
(
stderr
,
" arrrrrrrrrrrrrg Up cannot escape itself
\n
"
);
}
mi_user_level
--
;
}
void
EbmlParser
::
Down
(
void
)
{
mi_user_level
++
;
mi_level
++
;
}
void
EbmlParser
::
Keep
(
void
)
{
mb_keep
=
VLC_TRUE
;
}
int
EbmlParser
::
GetLevel
(
void
)
{
return
mi_user_level
;
}
EbmlElement
*
EbmlParser
::
Get
(
void
)
{
int
i_ulev
=
0
;
if
(
mi_user_level
!=
mi_level
)
{
return
NULL
;
}
if
(
m_got
)
{
EbmlElement
*
ret
=
m_got
;
m_got
=
NULL
;
return
ret
;
}
if
(
m_el
[
mi_level
]
)
{
m_el
[
mi_level
]
->
SkipData
(
*
m_es
,
m_el
[
mi_level
]
->
Generic
().
Context
);
if
(
!
mb_keep
)
{
delete
m_el
[
mi_level
];
}
mb_keep
=
VLC_FALSE
;
}
m_el
[
mi_level
]
=
m_es
->
FindNextElement
(
m_el
[
mi_level
-
1
]
->
Generic
().
Context
,
i_ulev
,
0xFFFFFFFFL
,
true
,
1
);
if
(
i_ulev
>
0
)
{
while
(
i_ulev
>
0
)
{
if
(
mi_level
==
1
)
{
mi_level
=
0
;
return
NULL
;
}
delete
m_el
[
mi_level
-
1
];
m_got
=
m_el
[
mi_level
-
1
]
=
m_el
[
mi_level
];
m_el
[
mi_level
]
=
NULL
;
mi_level
--
;
i_ulev
--
;
}
return
NULL
;
}
else
if
(
m_el
[
mi_level
]
==
NULL
)
{
fprintf
(
stderr
,
" m_el[mi_level] == NULL
\n
"
);
}
return
m_el
[
mi_level
];
}
/*****************************************************************************
* Tools
* * LoadCues : load the cues element and update index
*
* * LoadTags : load ... the tags element
*
* * InformationsCreate : create all informations, load tags if present
*
*****************************************************************************/
static
void
LoadCues
(
input_thread_t
*
p_input
)
{
demux_sys_t
*
p_sys
=
p_input
->
p_demux_data
;
int64_t
i_sav_position
=
p_sys
->
in
->
getFilePointer
();
EbmlParser
*
ep
;
EbmlElement
*
el
,
*
cues
;
msg_Dbg
(
p_input
,
"loading cues"
);
p_sys
->
in
->
setFilePointer
(
p_sys
->
i_cues_position
,
seek_beginning
);
cues
=
p_sys
->
es
->
FindNextID
(
KaxCues
::
ClassInfos
,
0xFFFFFFFFL
);
if
(
cues
==
NULL
)
{
msg_Err
(
p_input
,
"cannot load cues (broken seekhead or file)"
);
return
;
}
ep
=
new
EbmlParser
(
p_sys
->
es
,
cues
);
while
(
(
el
=
ep
->
Get
()
)
!=
NULL
)
{
if
(
EbmlId
(
*
el
)
==
KaxCuePoint
::
ClassInfos
.
GlobalId
)
{
#define idx p_sys->index[p_sys->i_index]
idx
.
i_track
=
-
1
;
idx
.
i_block_number
=
-
1
;
idx
.
i_position
=
-
1
;
idx
.
i_time
=
-
1
;
idx
.
b_key
=
VLC_TRUE
;
ep
->
Down
();
while
(
(
el
=
ep
->
Get
()
)
!=
NULL
)
{
if
(
EbmlId
(
*
el
)
==
KaxCueTime
::
ClassInfos
.
GlobalId
)
{
KaxCueTime
&
ctime
=
*
(
KaxCueTime
*
)
el
;
ctime
.
ReadData
(
p_sys
->
es
->
I_O
()
);
idx
.
i_time
=
uint64
(
ctime
)
*
(
mtime_t
)
1000000000
/
p_sys
->
i_timescale
;
}
else
if
(
EbmlId
(
*
el
)
==
KaxCueTrackPositions
::
ClassInfos
.
GlobalId
)
{
ep
->
Down
();
while
(
(
el
=
ep
->
Get
()
)
!=
NULL
)
{
if
(
EbmlId
(
*
el
)
==
KaxCueTrack
::
ClassInfos
.
GlobalId
)
{
KaxCueTrack
&
ctrack
=
*
(
KaxCueTrack
*
)
el
;
ctrack
.
ReadData
(
p_sys
->
es
->
I_O
()
);
idx
.
i_track
=
uint16
(
ctrack
);
}
else
if
(
EbmlId
(
*
el
)
==
KaxCueClusterPosition
::
ClassInfos
.
GlobalId
)
{
KaxCueClusterPosition
&
ccpos
=
*
(
KaxCueClusterPosition
*
)
el
;
ccpos
.
ReadData
(
p_sys
->
es
->
I_O
()
);
idx
.
i_position
=
p_sys
->
segment
->
GetGlobalPosition
(
uint64
(
ccpos
)
);
}
else
if
(
EbmlId
(
*
el
)
==
KaxCueBlockNumber
::
ClassInfos
.
GlobalId
)
{
KaxCueBlockNumber
&
cbnum
=
*
(
KaxCueBlockNumber
*
)
el
;
cbnum
.
ReadData
(
p_sys
->
es
->
I_O
()
);
idx
.
i_block_number
=
uint32
(
cbnum
);
}
else
{
msg_Dbg
(
p_input
,
" * Unknow (%s)"
,
typeid
(
*
el
).
name
()
);
}
}
ep
->
Up
();
}
else
{
msg_Dbg
(
p_input
,
" * Unknow (%s)"
,
typeid
(
*
el
).
name
()
);
}
}
ep
->
Up
();
msg_Dbg
(
p_input
,
" * added time=%lld pos=%lld track=%d bnum=%d"
,
idx
.
i_time
,
idx
.
i_position
,
idx
.
i_track
,
idx
.
i_block_number
);
p_sys
->
i_index
++
;
if
(
p_sys
->
i_index
>=
p_sys
->
i_index_max
)
{
p_sys
->
i_index_max
+=
1024
;
p_sys
->
index
=
(
mkv_index_t
*
)
realloc
(
p_sys
->
index
,
sizeof
(
mkv_index_t
)
*
p_sys
->
i_index_max
);
}
#undef idx
}
else
{
msg_Dbg
(
p_input
,
" * Unknow (%s)"
,
typeid
(
*
el
).
name
()
);
}
}
delete
ep
;
delete
cues
;
p_sys
->
b_cues
=
VLC_TRUE
;
msg_Dbg
(
p_input
,
"loading cues done."
);
p_sys
->
in
->
setFilePointer
(
i_sav_position
,
seek_beginning
);
}
static
void
LoadTags
(
input_thread_t
*
p_input
)
{
demux_sys_t
*
p_sys
=
p_input
->
p_demux_data
;
int64_t
i_sav_position
=
p_sys
->
in
->
getFilePointer
();
EbmlParser
*
ep
;
EbmlElement
*
el
,
*
tags
;
msg_Dbg
(
p_input
,
"loading tags"
);
p_sys
->
in
->
setFilePointer
(
p_sys
->
i_tags_position
,
seek_beginning
);
tags
=
p_sys
->
es
->
FindNextID
(
KaxTags
::
ClassInfos
,
0xFFFFFFFFL
);
if
(
tags
==
NULL
)
{
msg_Err
(
p_input
,
"cannot load tags (broken seekhead or file)"
);
return
;
}
msg_Dbg
(
p_input
,
"Tags"
);
ep
=
new
EbmlParser
(
p_sys
->
es
,
tags
);
while
(
(
el
=
ep
->
Get
()
)
!=
NULL
)
{
if
(
EbmlId
(
*
el
)
==
KaxTag
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"+ Tag"
);
ep
->
Down
();
while
(
(
el
=
ep
->
Get
()
)
!=
NULL
)
{
if
(
EbmlId
(
*
el
)
==
KaxTagTargets
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"| + Targets"
);
ep
->
Down
();
while
(
(
el
=
ep
->
Get
()
)
!=
NULL
)
{
msg_Dbg
(
p_input
,
"| | + Unknown (%s)"
,
typeid
(
*
el
).
name
()
);
}
ep
->
Up
();
}
else
if
(
EbmlId
(
*
el
)
==
KaxTagGeneral
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"| + General"
);
ep
->
Down
();
while
(
(
el
=
ep
->
Get
()
)
!=
NULL
)
{
msg_Dbg
(
p_input
,
"| | + Unknown (%s)"
,
typeid
(
*
el
).
name
()
);
}
ep
->
Up
();
}
else
if
(
EbmlId
(
*
el
)
==
KaxTagGenres
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"| + Genres"
);
ep
->
Down
();
while
(
(
el
=
ep
->
Get
()
)
!=
NULL
)
{
msg_Dbg
(
p_input
,
"| | + Unknown (%s)"
,
typeid
(
*
el
).
name
()
);
}
ep
->
Up
();
}
else
if
(
EbmlId
(
*
el
)
==
KaxTagAudioSpecific
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"| + Audio Specific"
);
ep
->
Down
();
while
(
(
el
=
ep
->
Get
()
)
!=
NULL
)
{
msg_Dbg
(
p_input
,
"| | + Unknown (%s)"
,
typeid
(
*
el
).
name
()
);
}
ep
->
Up
();
}
else
if
(
EbmlId
(
*
el
)
==
KaxTagImageSpecific
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"| + Images Specific"
);
ep
->
Down
();
while
(
(
el
=
ep
->
Get
()
)
!=
NULL
)
{
msg_Dbg
(
p_input
,
"| | + Unknown (%s)"
,
typeid
(
*
el
).
name
()
);
}
ep
->
Up
();
}
else
if
(
EbmlId
(
*
el
)
==
KaxTagMultiComment
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"| + Multi Comment"
);
}
else
if
(
EbmlId
(
*
el
)
==
KaxTagMultiCommercial
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"| + Multi Commercial"
);
}
else
if
(
EbmlId
(
*
el
)
==
KaxTagMultiDate
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"| + Multi Date"
);
}
else
if
(
EbmlId
(
*
el
)
==
KaxTagMultiEntity
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"| + Multi Entity"
);
}
else
if
(
EbmlId
(
*
el
)
==
KaxTagMultiIdentifier
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"| + Multi Identifier"
);
}
else
if
(
EbmlId
(
*
el
)
==
KaxTagMultiLegal
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"| + Multi Legal"
);
}
else
if
(
EbmlId
(
*
el
)
==
KaxTagMultiTitle
::
ClassInfos
.
GlobalId
)
{
msg_Dbg
(
p_input
,
"| + Multi Title"
);
}
else
{
msg_Dbg
(
p_input
,
"| + Unknown (%s)"
,
typeid
(
*
el
).
name
()
);
}
}
ep
->
Up
();
}
else
{
msg_Dbg
(
p_input
,
"+ Unknown (%s)"
,
typeid
(
*
el
).
name
()
);
}
}
delete
ep
;
delete
tags
;
msg_Dbg
(
p_input
,
"loading tags done."
);
p_sys
->
in
->
setFilePointer
(
i_sav_position
,
seek_beginning
);
}
static
void
InformationsCreate
(
input_thread_t
*
p_input
)
{
demux_sys_t
*
p_sys
=
p_input
->
p_demux_data
;
input_info_category_t
*
p_cat
;
int
i_track
;
p_cat
=
input_InfoCategory
(
p_input
,
"Matroska"
);
if
(
p_sys
->
f_duration
>
1000.1
)
{
int64_t
i_sec
=
(
int64_t
)
p_sys
->
f_duration
/
1000
;
int
h
,
m
,
s
;
h
=
i_sec
/
3600
;
m
=
(
i_sec
/
60
)
%
60
;
s
=
i_sec
%
60
;
input_AddInfo
(
p_cat
,
_
(
"Duration"
),
"%d:%2.2d:%2.2d"
,
h
,
m
,
s
);
}
if
(
p_sys
->
psz_title
)
{
input_AddInfo
(
p_cat
,
_
(
"Title"
),
"%s"
,
p_sys
->
psz_title
);
}
if
(
p_sys
->
psz_date_utc
)
{
input_AddInfo
(
p_cat
,
_
(
"Date UTC"
),
"%s"
,
p_sys
->
psz_date_utc
);
}
if
(
p_sys
->
psz_segment_filename
)
{
input_AddInfo
(
p_cat
,
_
(
"Segment Filename"
),
"%s"
,
p_sys
->
psz_segment_filename
);
}
if
(
p_sys
->
psz_muxing_application
)
{
input_AddInfo
(
p_cat
,
_
(
"Muxing Application"
),
"%s"
,
p_sys
->
psz_muxing_application
);
}
if
(
p_sys
->
psz_writing_application
)
{
input_AddInfo
(
p_cat
,
_
(
"Writing Application"
),
"%s"
,
p_sys
->
psz_writing_application
);
}
input_AddInfo
(
p_cat
,
_
(
"Number of streams"
),
"%d"
,
p_sys
->
i_track
);
for
(
i_track
=
0
;
i_track
<
p_sys
->
i_track
;
i_track
++
)
{
char
psz_cat
[
strlen
(
"Stream "
)
+
10
];
#define tk p_sys->track[i_track]
sprintf
(
psz_cat
,
"Stream %d"
,
i_track
);
p_cat
=
input_InfoCategory
(
p_input
,
psz_cat
);
switch
(
tk
.
i_cat
)
{
case
AUDIO_ES
:
input_AddInfo
(
p_cat
,
_
(
"Type"
),
_
(
"Audio"
)
);
input_AddInfo
(
p_cat
,
_
(
"Codec"
),
"%.4s (%s)"
,
(
char
*
)
&
tk
.
i_codec
,
tk
.
psz_codec
);
if
(
tk
.
i_channels
>
0
)
{
input_AddInfo
(
p_cat
,
_
(
"Channels"
),
"%d"
,
tk
.
i_channels
);
}
if
(
tk
.
i_samplerate
>
0
)
{
input_AddInfo
(
p_cat
,
_
(
"Sample Rate"
),
"%d"
,
tk
.
i_samplerate
);
}
if
(
tk
.
i_bitspersample
)
{
input_AddInfo
(
p_cat
,
_
(
"Bits Per Sample"
),
"%d"
,
tk
.
i_bitspersample
);
}
break
;
case
VIDEO_ES
:
input_AddInfo
(
p_cat
,
_
(
"Type"
),
_
(
"Video"
)
);
input_AddInfo
(
p_cat
,
_
(
"Codec"
),
"%.4s (%s)"
,
(
char
*
)
&
tk
.
i_codec
,
tk
.
psz_codec
);
if
(
tk
.
i_width
>
0
&&
tk
.
i_height
)
{
input_AddInfo
(
p_cat
,
_
(
"Resolution"
),
"%dx%d"
,
tk
.
i_width
,
tk
.
i_height
);
}
if
(
tk
.
i_display_width
>
0
&&
tk
.
i_display_height
)
{
input_AddInfo
(
p_cat
,
_
(
"Display Resolution"
),
"%dx%d"
,
tk
.
i_display_width
,
tk
.
i_display_height
);
}
if
(
tk
.
f_fps
>
0.1
)
{
input_AddInfo
(
p_cat
,
_
(
"Frame Per Second"
),
"%.3f"
,
tk
.
f_fps
);
}
break
;
case
SPU_ES
:
input_AddInfo
(
p_cat
,
_
(
"Type"
),
_
(
"Subtitle"
)
);
input_AddInfo
(
p_cat
,
_
(
"Codec"
),
"%s"
,
tk
.
psz_codec
);
break
;
}
#undef tk
}
if
(
p_sys
->
i_tags_position
>=
0
&&
p_input
->
stream
.
b_seekable
)
{
LoadTags
(
p_input
);
}
}
/*****************************************************************************
* Divers
*****************************************************************************/
static
void
IndexAppendCluster
(
input_thread_t
*
p_input
,
KaxCluster
*
cluster
)
{
demux_sys_t
*
p_sys
=
p_input
->
p_demux_data
;
#define idx p_sys->index[p_sys->i_index]
idx
.
i_track
=
-
1
;
idx
.
i_block_number
=
-
1
;
idx
.
i_position
=
cluster
->
GetElementPosition
();
idx
.
i_time
=
-
1
;
idx
.
b_key
=
VLC_TRUE
;
p_sys
->
i_index
++
;
if
(
p_sys
->
i_index
>=
p_sys
->
i_index_max
)
{
p_sys
->
i_index_max
+=
1024
;
p_sys
->
index
=
(
mkv_index_t
*
)
realloc
(
p_sys
->
index
,
sizeof
(
mkv_index_t
)
*
p_sys
->
i_index_max
);
}
#undef idx
}
static
char
*
UTF8ToStr
(
const
UTFstring
&
u
)
{
int
i_src
;
const
wchar_t
*
src
;
char
*
dst
,
*
p
;
i_src
=
u
.
length
();
src
=
u
.
c_str
();
p
=
dst
=
(
char
*
)
malloc
(
i_src
+
1
);
while
(
i_src
>
0
)
{
if
(
*
src
<
255
)
{
*
p
++
=
(
char
)
*
src
;
}
else
{
*
p
++
=
'?'
;
}
src
++
;
i_src
--
;
}
*
p
++=
'\0'
;
return
dst
;
}
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