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
9cbc047c
Commit
9cbc047c
authored
Nov 22, 2003
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* mpegvideo: ported to new API (need more clean up).
parent
294d2ef0
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
386 additions
and
444 deletions
+386
-444
modules/packetizer/mpegvideo.c
modules/packetizer/mpegvideo.c
+386
-444
No files found.
modules/packetizer/mpegvideo.c
View file @
9cbc047c
...
...
@@ -2,7 +2,7 @@
* mpegvideo.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: mpegvideo.c,v 1.2
1 2003/11/21 15:32:08
fenrir Exp $
* $Id: mpegvideo.c,v 1.2
2 2003/11/22 16:53:02
fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
...
...
@@ -39,537 +39,479 @@
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h>
/* malloc(), free() */
#include <vlc/vlc.h>
#include <vlc/decoder.h>
#include <vlc/input.h>
#include <vlc/sout.h>
#include "codecs.h"
/* WAVEFORMATEX BITMAPINFOHEADER */
#include <stdlib.h>
/* malloc(), free() */
#include <string.h>
/* strdup() */
/*****************************************************************************
* Local prototypes
*****************************************************************************/
typedef
struct
packetizer_s
{
/* Input properties */
decoder_fifo_t
*
p_fifo
;
bit_stream_t
bit_stream
;
/* Output properties */
sout_packetizer_input_t
*
p_sout_input
;
es_format_t
output_format
;
mtime_t
i_interpolated_dts
;
mtime_t
i_old_duration
;
mtime_t
i_last_ref_pts
;
double
d_frame_rate
;
int
i_progressive_sequence
;
int
i_low_delay
;
uint8_t
p_sequence_header
[
150
];
int
i_sequence_header_length
;
int
i_last_sequence_header
;
vlc_bool_t
b_expect_discontinuity
;
}
packetizer_t
;
static
int
Open
(
vlc_object_t
*
);
static
int
Run
(
decoder_fifo_t
*
);
static
int
InitThread
(
packetizer_t
*
);
static
void
PacketizeThread
(
packetizer_t
*
);
static
void
EndThread
(
packetizer_t
*
);
static
void
BitstreamCallback
(
bit_stream_t
*
,
vlc_bool_t
);
/*****************************************************************************
* Module descriptor
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
vlc_module_begin
();
set_description
(
_
(
"MPEG-I/II video packetizer"
)
);
set_capability
(
"packetizer"
,
50
);
set_callbacks
(
Open
,
NULL
);
set_callbacks
(
Open
,
Close
);
vlc_module_end
();
/*****************************************************************************
* OpenDecoder: probe the packetizer and return score
*****************************************************************************
* Tries to launch a decoder and return score so that the interface is able
* to choose.
* Local prototypes
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
p_this
)
{
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
static
block_t
*
Packetize
(
decoder_t
*
,
block_t
**
);
if
(
p_dec
->
p_fifo
->
i_fourcc
!=
VLC_FOURCC
(
'm'
,
'p'
,
'g'
,
'v'
)
&&
p_dec
->
p_fifo
->
i_fourcc
!=
VLC_FOURCC
(
'm'
,
'p'
,
'g'
,
'1'
)
&&
p_dec
->
p_fifo
->
i_fourcc
!=
VLC_FOURCC
(
'm'
,
'p'
,
'g'
,
'2'
)
)
{
return
VLC_EGENERIC
;
}
static
int
mpgv_FindStartCode
(
uint8_t
**
pp_start
,
uint8_t
*
p_end
);
p_dec
->
pf_run
=
Run
;
return
VLC_SUCCESS
;
}
struct
decoder_sys_t
{
/* sequence header and extention */
block_t
*
p_seq
;
block_t
*
p_ext
;
/* current frame being building */
block_t
*
p_frame
;
vlc_bool_t
b_frame_slice
;
vlc_bool_t
b_frame_corrupted
;
vlc_bool_t
b_gop
;
/* pts of current picture */
mtime_t
i_pts
;
mtime_t
i_dts
;
/* gathering buffer */
int
i_buffer
;
int
i_buffer_size
;
uint8_t
*
p_buffer
;
uint8_t
*
p_start
,
*
p_old
;
/* */
int
i_frame_rate
;
int
i_frame_rate_base
;
vlc_bool_t
b_seq_progressive
;
vlc_bool_t
b_low_delay
;
/* */
int
i_temporal_ref
;
int
i_picture_type
;
int
i_picture_structure
;
int
i_top_field_first
;
int
i_repeat_first_field
;
int
i_progressive_frame
;
/* */
int
i_seq_old
;
/* How many picture from last seq */
/* */
mtime_t
i_interpolated_dts
;
mtime_t
i_old_duration
;
mtime_t
i_last_ref_pts
;
};
/*****************************************************************************
*
RunDecoder: this function is called just after the thread is created
*
Open:
*****************************************************************************/
static
int
Run
(
decoder_fifo_t
*
p_fifo
)
static
int
Open
(
vlc_object_t
*
p_this
)
{
packetizer_t
*
p_pack
;
int
b_error
;
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
decoder_sys_t
*
p_sys
;
msg_Info
(
p_fifo
,
"Running mpegvideo packetizer"
);
if
(
!
(
p_pack
=
malloc
(
sizeof
(
packetizer_t
)
)
)
)
if
(
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
'm'
,
'p'
,
'g'
,
'1'
)
&&
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
'm'
,
'p'
,
'g'
,
'2'
)
&&
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
'm'
,
'p'
,
'g'
,
'v'
)
)
{
msg_Err
(
p_fifo
,
"out of memory"
);
DecoderError
(
p_fifo
);
return
(
-
1
);
return
VLC_EGENERIC
;
}
memset
(
p_pack
,
0
,
sizeof
(
packetizer_t
)
);
p_pack
->
p_fifo
=
p_fifo
;
es_format_Init
(
&
p_dec
->
fmt_out
,
VIDEO_ES
,
VLC_FOURCC
(
'm'
,
'p'
,
'g'
,
'v'
)
);
p_dec
->
pf_packetize
=
Packetize
;
if
(
InitThread
(
p_pack
)
!=
0
)
{
DecoderError
(
p_fifo
);
return
(
-
1
);
}
p_dec
->
p_sys
=
p_sys
=
malloc
(
sizeof
(
decoder_sys_t
)
);
while
(
(
!
p_pack
->
p_fifo
->
b_die
)
&&
(
!
p_pack
->
p_fifo
->
b_error
)
)
{
PacketizeThread
(
p_pack
);
}
p_sys
->
p_seq
=
NULL
;
p_sys
->
p_ext
=
NULL
;
p_sys
->
p_frame
=
NULL
;
p_sys
->
b_frame_slice
=
VLC_FALSE
;
p_sys
->
b_frame_corrupted
=
VLC_FALSE
;
p_sys
->
b_gop
=
VLC_FALSE
;
p_sys
->
i_buffer
=
0
;
p_sys
->
i_buffer_size
=
10000
;
p_sys
->
p_buffer
=
malloc
(
p_sys
->
i_buffer_size
);
p_sys
->
p_start
=
p_sys
->
p_buffer
;
p_sys
->
p_old
=
NULL
;
if
(
(
b_error
=
p_pack
->
p_fifo
->
b_error
)
)
{
DecoderError
(
p_pack
->
p_fifo
);
}
p_sys
->
i_dts
=
0
;
p_sys
->
i_pts
=
0
;
EndThread
(
p_pack
);
p_sys
->
i_frame_rate
=
1
;
p_sys
->
i_frame_rate_base
=
1
;
p_sys
->
b_seq_progressive
=
VLC_TRUE
;
p_sys
->
b_low_delay
=
VLC_TRUE
;
p_sys
->
i_seq_old
=
0
;
if
(
p_pack
)
{
free
(
p_pack
);
}
p_sys
->
i_temporal_ref
=
0
;
p_sys
->
i_picture_type
=
0
;
p_sys
->
i_picture_structure
=
0x03
;
/* frame */
p_sys
->
i_top_field_first
=
0
;
p_sys
->
i_repeat_first_field
=
0
;
p_sys
->
i_progressive_frame
=
0
;
if
(
b_error
)
{
return
(
-
1
);
}
p_sys
->
i_interpolated_dts
=
0
;
p_sys
->
i_old_duration
=
0
;
p_sys
->
i_last_ref_pts
=
0
;
return
(
0
)
;
return
VLC_SUCCESS
;
}
/*****************************************************************************
*
InitThread: initialize data before entering main loop
*
Close:
*****************************************************************************/
static
int
InitThread
(
packetizer_t
*
p_pack
)
static
void
Close
(
vlc_object_t
*
p_this
)
{
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
p_pack
->
output_format
.
i_cat
=
VIDEO_ES
;
p_pack
->
output_format
.
i_codec
=
VLC_FOURCC
(
'm'
,
'p'
,
'g'
,
'v'
);
p_pack
->
output_format
.
video
.
i_width
=
0
;
p_pack
->
output_format
.
video
.
i_height
=
0
;
p_pack
->
output_format
.
i_bitrate
=
0
;
p_pack
->
output_format
.
i_extra
=
0
;
p_pack
->
output_format
.
p_extra
=
NULL
;
p_pack
->
b_expect_discontinuity
=
0
;
p_pack
->
p_sout_input
=
NULL
;
if
(
InitBitstream
(
&
p_pack
->
bit_stream
,
p_pack
->
p_fifo
,
BitstreamCallback
,
(
void
*
)
p_pack
)
!=
VLC_SUCCESS
)
if
(
p_sys
->
p_seq
)
{
msg_Err
(
p_pack
->
p_fifo
,
"cannot initialize bitstream"
);
return
-
1
;
block_Release
(
p_sys
->
p_seq
);
}
return
(
0
);
}
/* from ISO 13818-2 */
/* converting frame_rate_code to frame_rate */
static
const
double
pd_frame_rates
[
16
]
=
{
0
,
24000
.
0
/
1001
,
24
,
25
,
30000
.
0
/
1001
,
30
,
50
,
60000
.
0
/
1001
,
60
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
static
int
CopyUntilNextStartCode
(
packetizer_t
*
p_pack
,
sout_buffer_t
*
p_sout_buffer
,
unsigned
int
*
pi_pos
)
{
int
i_copy
=
0
;
do
if
(
p_sys
->
p_ext
)
{
p_sout_buffer
->
p_buffer
[(
*
pi_pos
)
++
]
=
GetBits
(
&
p_pack
->
bit_stream
,
8
);
i_copy
++
;
if
(
*
pi_pos
+
2048
>
p_sout_buffer
->
i_buffer_size
)
{
sout_BufferRealloc
(
p_pack
->
p_sout_input
->
p_sout
,
p_sout_buffer
,
p_sout_buffer
->
i_buffer_size
+
50
*
1024
);
}
}
while
(
ShowBits
(
&
p_pack
->
bit_stream
,
24
)
!=
0x01
&&
!
p_pack
->
p_fifo
->
b_die
&&
!
p_pack
->
p_fifo
->
b_error
);
return
(
i_copy
);
block_Release
(
p_sys
->
p_ext
);
}
if
(
p_sys
->
p_frame
)
{
block_Release
(
p_sys
->
p_frame
);
}
free
(
p_sys
->
p_buffer
);
free
(
p_sys
);
}
/*****************************************************************************
* Packetize
Thread: packetize an unit (here copy a complete pes)
* Packetize
:
*****************************************************************************/
static
void
PacketizeThread
(
packetizer_t
*
p_pa
ck
)
static
block_t
*
Packetize
(
decoder_t
*
p_dec
,
block_t
**
pp_blo
ck
)
{
sout_buffer_t
*
p_sout_buffer
=
NULL
;
vlc_bool_t
b_seen_slice
=
VLC_FALSE
;
int32_t
i_pos
;
int
i_skipped
;
mtime_t
i_duration
;
/* of the parsed picture */
mtime_t
i_pts
=
0
;
mtime_t
i_dts
=
0
;
/* needed to calculate pts/dts */
int
i_temporal_ref
=
0
;
int
i_picture_coding_type
=
0
;
int
i_picture_structure
=
0x03
;
/* frame picture */
int
i_top_field_first
=
0
;
int
i_repeat_first_field
=
0
;
int
i_progressive_frame
=
0
;
if
(
!
p_pack
->
p_sout_input
)
{
byte_t
p_temp
[
512
];
/* 150 bytes is the maximal size
of a sequence_header + sequence_extension */
int
i_frame_rate_code
;
/* skip data until we find a sequence_header_code */
/* TODO: store skipped somewhere so can send it to the mux
* after the input is created */
i_skipped
=
0
;
while
(
ShowBits
(
&
p_pack
->
bit_stream
,
32
)
!=
0x1B3
&&
!
p_pack
->
p_fifo
->
b_die
&&
!
p_pack
->
p_fifo
->
b_error
)
{
RemoveBits
(
&
p_pack
->
bit_stream
,
8
);
i_skipped
++
;
}
msg_Warn
(
p_pack
->
p_fifo
,
"sequence_header_code found (%d skipped)"
,
i_skipped
);
/* copy the start_code */
i_pos
=
0
;
GetChunk
(
&
p_pack
->
bit_stream
,
p_temp
,
4
);
i_pos
+=
4
;
/* horizontal_size_value */
p_pack
->
output_format
.
video
.
i_width
=
ShowBits
(
&
p_pack
->
bit_stream
,
12
);
/* vertical_size_value */
p_pack
->
output_format
.
video
.
i_height
=
ShowBits
(
&
p_pack
->
bit_stream
,
24
)
&
0xFFF
;
/* frame_rate_code */
i_frame_rate_code
=
ShowBits
(
&
p_pack
->
bit_stream
,
32
)
&
0xF
;
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
block_t
*
p_chain_out
=
NULL
;
block_t
*
p_block
;
/* copy headers */
GetChunk
(
&
p_pack
->
bit_stream
,
p_temp
+
i_pos
,
7
);
i_pos
+=
7
;
if
(
pp_block
==
NULL
||
*
pp_block
==
NULL
)
{
return
NULL
;
}
p_block
=
*
pp_block
;
*
pp_block
=
NULL
;
/* intra_quantiser_matrix [non_intra_quantiser_matrix] */
if
(
ShowBits
(
&
p_pack
->
bit_stream
,
7
)
&
0x1
)
{
if
(
p_block
->
b_discontinuity
)
{
p_sys
->
b_frame_corrupted
=
VLC_TRUE
;
}
GetChunk
(
&
p_pack
->
bit_stream
,
p_temp
+
i_pos
,
64
);
i_pos
+=
64
;
/* Append data */
if
(
p_sys
->
i_buffer
+
p_block
->
i_buffer
>
p_sys
->
i_buffer_size
)
{
uint8_t
*
p_buffer
=
p_sys
->
p_buffer
;
if
(
ShowBits
(
&
p_pack
->
bit_stream
,
8
)
&
0x1
)
{
GetChunk
(
&
p_pack
->
bit_stream
,
p_temp
+
i_pos
,
65
);
i_pos
+=
65
;
}
}
/* non_intra_quantiser_matrix */
else
if
(
ShowBits
(
&
p_pack
->
bit_stream
,
8
)
&
0x1
)
{
GetChunk
(
&
p_pack
->
bit_stream
,
p_temp
+
i_pos
,
65
);
i_pos
+=
65
;
}
/* nothing */
else
{
GetChunk
(
&
p_pack
->
bit_stream
,
p_temp
+
i_pos
,
1
);
i_pos
+=
1
;
}
p_sys
->
i_buffer_size
+=
p_block
->
i_buffer
+
1024
;
p_sys
->
p_buffer
=
realloc
(
p_sys
->
p_buffer
,
p_sys
->
i_buffer_size
);
/* sequence_extension (10 bytes) */
if
(
ShowBits
(
&
p_pack
->
bit_stream
,
32
)
!=
0x1B5
)
if
(
p_sys
->
p_start
)
{
msg_Dbg
(
p_pack
->
p_fifo
,
"ARRGG no extension_start_code"
);
p_pack
->
i_progressive_sequence
=
1
;
p_pack
->
i_low_delay
=
1
;
p_sys
->
p_start
=
p_sys
->
p_start
-
p_buffer
+
p_sys
->
p_buffer
;
}
else
if
(
p_sys
->
p_old
)
{
GetChunk
(
&
p_pack
->
bit_stream
,
p_temp
+
i_pos
,
10
);
p_pack
->
i_progressive_sequence
=
(
p_temp
[
i_pos
+
5
]
&
0x08
)
?
1
:
0
;
p_pack
->
i_low_delay
=
(
p_temp
[
i_pos
+
9
]
&
0x80
)
?
1
:
0
;
i_pos
+=
10
;
p_sys
->
p_old
=
p_sys
->
p_old
-
p_buffer
+
p_sys
->
p_buffer
;
}
/* remember sequence_header and sequence_extention */
memcpy
(
p_pack
->
p_sequence_header
,
p_temp
,
i_pos
);
p_pack
->
i_sequence_header_length
=
i_pos
;
p_pack
->
d_frame_rate
=
pd_frame_rates
[
i_frame_rate_code
];
msg_Warn
(
p_pack
->
p_fifo
,
"creating input (image size %dx%d, frame rate %.2f)"
,
p_pack
->
output_format
.
video
.
i_width
,
p_pack
->
output_format
.
video
.
i_height
,
p_pack
->
d_frame_rate
);
/* now we have informations to create the input */
p_pack
->
p_sout_input
=
sout_InputNew
(
p_pack
->
p_fifo
,
&
p_pack
->
output_format
);
if
(
!
p_pack
->
p_sout_input
)
{
msg_Err
(
p_pack
->
p_fifo
,
"cannot add a new stream"
);
p_pack
->
p_fifo
->
b_error
=
VLC_TRUE
;
return
;
}
}
memcpy
(
&
p_sys
->
p_buffer
[
p_sys
->
i_buffer
],
p_block
->
p_buffer
,
p_block
->
i_buffer
);
p_sys
->
i_buffer
+=
p_block
->
i_buffer
;
p_sout_buffer
=
sout_BufferNew
(
p_pack
->
p_sout_input
->
p_sout
,
100
*
1024
);
p_sout_buffer
->
i_size
=
i_pos
;
memcpy
(
p_sout_buffer
->
p_buffer
,
p_temp
,
i_pos
);
}
else
if
(
p_sys
->
i_buffer
>
10
*
1000000
)
{
p_sout_buffer
=
sout_BufferNew
(
p_pack
->
p_sout_input
->
p_sout
,
100
*
1024
);
i_pos
=
0
;
msg_Err
(
p_dec
,
"mmh reseting context"
);
p_sys
->
i_buffer
=
0
;
}
p_pack
->
i_last_sequence_header
++
;
/* Split data in block */
for
(
;;
)
{
uint32_t
i_code
;
if
(
p_pack
->
p_fifo
->
b_die
||
p_pack
->
p_fifo
->
b_error
)
if
(
mpgv_FindStartCode
(
&
p_sys
->
p_start
,
&
p_sys
->
p_buffer
[
p_sys
->
i_buffer
]
)
)
{
break
;
}
i_code
=
ShowBits
(
&
p_pack
->
bit_stream
,
32
);
if
(
b_seen_slice
&&
(
i_code
<
0x101
||
i_code
>
0x1af
)
)
{
break
;
}
block_Release
(
p_block
);
if
(
i_code
==
0x1B8
)
/* GOP */
{
/* usefull for bad MPEG-1 : repeat the sequence_header
every second */
if
(
p_pack
->
i_last_sequence_header
>
(
int
)
p_pack
->
d_frame_rate
)
if
(
p_sys
->
p_seq
==
NULL
)
{
memcpy
(
p_sout_buffer
->
p_buffer
+
i_pos
,
p_pack
->
p_sequence_header
,
p_pack
->
i_sequence_header_length
);
i_pos
+=
p_pack
->
i_sequence_header_length
;
p_pack
->
i_last_sequence_header
=
0
;
block_ChainRelease
(
p_chain_out
);
return
NULL
;
}
p_sout_buffer
->
i_flags
|=
SOUT_BUFFER_FLAGS_GOP
;
CopyUntilNextStartCode
(
p_pack
,
p_sout_buffer
,
&
i_pos
);
return
p_chain_out
;
}
else
if
(
i_code
==
0x100
)
/* Picture */
{
/* picture_start_code */
GetChunk
(
&
p_pack
->
bit_stream
,
p_sout_buffer
->
p_buffer
+
i_pos
,
4
);
i_pos
+=
4
;
NextPTS
(
&
p_pack
->
bit_stream
,
&
i_pts
,
&
i_dts
);
i_temporal_ref
=
ShowBits
(
&
p_pack
->
bit_stream
,
10
);
i_picture_coding_type
=
ShowBits
(
&
p_pack
->
bit_stream
,
13
)
&
0x3
;
CopyUntilNextStartCode
(
p_pack
,
p_sout_buffer
,
&
i_pos
);
}
else
if
(
i_code
==
0x1b5
)
if
(
p_sys
->
p_old
)
{
/*
extention start code 32
*/
GetChunk
(
&
p_pack
->
bit_stream
,
p_sout_buffer
->
p_buffer
+
i_pos
,
4
);
i_pos
+=
4
;
/*
Extract the data
*/
int
i_frag
=
p_sys
->
p_start
-
p_sys
->
p_old
;
block_t
*
p_frag
=
block_New
(
p_dec
,
i_frag
)
;
if
(
ShowBits
(
&
p_pack
->
bit_stream
,
4
)
==
0x08
)
memcpy
(
p_frag
->
p_buffer
,
p_sys
->
p_old
,
i_frag
);
if
(
i_frag
<
p_sys
->
i_buffer
)
{
/* picture coding extention */
/* extention start code identifier(b1000) 4 */
/* f_code[2][2] 16 */
/* intra_dc_precision 2 */
/* picture_structure 2 */
/* top_field_first 1 */
i_picture_structure
=
ShowBits
(
&
p_pack
->
bit_stream
,
24
)
&
0x03
;
i_top_field_first
=
ShowBits
(
&
p_pack
->
bit_stream
,
25
)
&
0x01
;
i_repeat_first_field
=
ShowBits
(
&
p_pack
->
bit_stream
,
31
)
&
0x01
;
GetChunk
(
&
p_pack
->
bit_stream
,
p_sout_buffer
->
p_buffer
+
i_pos
,
4
);
i_pos
+=
4
;
i_progressive_frame
=
ShowBits
(
&
p_pack
->
bit_stream
,
1
)
&
0x01
;
memmove
(
p_sys
->
p_buffer
,
&
p_sys
->
p_buffer
[
i_frag
],
p_sys
->
i_buffer
-
i_frag
);
}
CopyUntilNextStartCode
(
p_pack
,
p_sout_buffer
,
&
i_pos
)
;
}
else
{
if
(
i_code
>=
0x101
&&
i_code
<=
0x1af
)
p_sys
->
i_buffer
-=
i_frag
;
p_sys
->
p_start
-=
i_frag
;
p_sys
->
p_old
-=
i_frag
;
if
(
p_sys
->
b_frame_slice
&&
(
p_frag
->
p_buffer
[
3
]
==
0x00
||
p_frag
->
p_buffer
[
3
]
>
0xaf
)
)
{
b_seen_slice
=
VLC_TRUE
;
/* We have a complete picture output it */
if
(
p_sys
->
p_seq
==
NULL
)
{
msg_Dbg
(
p_dec
,
"waiting sequence start"
);
block_ChainRelease
(
p_sys
->
p_frame
);
}
else
if
(
p_sys
->
i_dts
<=
0
&&
p_sys
->
i_pts
<=
0
&&
p_sys
->
i_interpolated_dts
<=
0
)
{
msg_Dbg
(
p_dec
,
"need a starting pts/dts"
);
block_ChainRelease
(
p_sys
->
p_frame
);
}
else
if
(
p_sys
->
b_frame_corrupted
)
{
msg_Warn
(
p_dec
,
"trashing a corrupted picture"
);
block_ChainRelease
(
p_sys
->
p_frame
);
p_sys
->
b_frame_corrupted
=
VLC_FALSE
;
}
else
{
block_t
*
p_pic
=
block_ChainGather
(
p_sys
->
p_frame
);
mtime_t
i_duration
=
(
mtime_t
)(
1000000
*
p_sys
->
i_frame_rate_base
/
p_sys
->
i_frame_rate
);
if
(
!
p_sys
->
b_seq_progressive
&&
p_sys
->
i_picture_structure
!=
0x03
)
{
i_duration
/=
2
;
}
if
(
p_sys
->
b_seq_progressive
)
{
if
(
p_sys
->
i_top_field_first
==
0
&&
p_sys
->
i_repeat_first_field
==
1
)
{
i_duration
*=
2
;
}
else
if
(
p_sys
->
i_top_field_first
==
1
&&
p_sys
->
i_repeat_first_field
==
1
)
{
i_duration
*=
3
;
}
}
else
{
if
(
p_sys
->
i_picture_structure
==
0x03
)
{
if
(
p_sys
->
i_progressive_frame
&&
p_sys
->
i_repeat_first_field
)
{
i_duration
+=
i_duration
/
2
;
}
}
}
if
(
p_sys
->
b_low_delay
||
p_sys
->
i_picture_type
==
0x03
)
{
/* Trivial case (DTS == PTS) */
/* Correct interpolated dts when we receive a new pts/dts */
if
(
p_sys
->
i_pts
>
0
)
p_sys
->
i_interpolated_dts
=
p_sys
->
i_pts
;
if
(
p_sys
->
i_dts
>
0
)
p_sys
->
i_interpolated_dts
=
p_sys
->
i_dts
;
}
else
{
/* Correct interpolated dts when we receive a new pts/dts */
if
(
p_sys
->
i_last_ref_pts
>
0
)
p_sys
->
i_interpolated_dts
=
p_sys
->
i_last_ref_pts
;
if
(
p_sys
->
i_dts
>
0
)
p_sys
->
i_interpolated_dts
=
p_sys
->
i_dts
;
p_sys
->
i_last_ref_pts
=
p_sys
->
i_pts
;
}
p_pic
->
i_dts
=
p_sys
->
i_interpolated_dts
;
/* Set PTS only if I frame or come from stream */
if
(
p_sys
->
i_pts
>
0
)
{
p_pic
->
i_pts
=
p_sys
->
i_pts
;
}
else
if
(
p_sys
->
i_picture_type
==
0x03
)
{
p_pic
->
i_pts
=
p_pic
->
i_dts
;
}
else
{
p_pic
->
i_pts
=
-
1
;
}
if
(
p_sys
->
b_low_delay
||
p_sys
->
i_picture_type
==
0x03
)
{
/* Trivial case (DTS == PTS) */
p_sys
->
i_interpolated_dts
+=
i_duration
;
}
else
{
p_sys
->
i_interpolated_dts
+=
p_sys
->
i_old_duration
;
p_sys
->
i_old_duration
=
i_duration
;
}
p_pic
->
i_length
=
p_sys
->
i_interpolated_dts
-
p_pic
->
i_dts
;
//msg_Dbg( p_dec, "pic: type=%d dts=%lld pts-dts=%lld", p_sys->i_picture_type, p_pic->i_dts, p_pic->i_pts - p_pic->i_dts);
block_ChainAppend
(
&
p_chain_out
,
p_pic
);
}
/* reset context */
p_sys
->
p_frame
=
NULL
;
p_sys
->
b_frame_slice
=
VLC_FALSE
;
p_sys
->
b_gop
=
VLC_FALSE
;
p_sys
->
i_pts
=
0
;
p_sys
->
i_dts
=
0
;
}
if
(
i_code
==
0x1B3
)
if
(
p_frag
->
p_buffer
[
3
]
==
0xb8
)
{
p_pack
->
i_last_sequence_header
=
0
;
if
(
p_sys
->
p_seq
&&
p_sys
->
i_seq_old
>
p_sys
->
i_frame_rate
/
p_sys
->
i_frame_rate_base
)
{
/* Usefull for mpeg1: repeat sequence header every second */
block_ChainAppend
(
&
p_sys
->
p_frame
,
block_Duplicate
(
p_sys
->
p_seq
)
);
if
(
p_sys
->
p_ext
)
{
block_ChainAppend
(
&
p_sys
->
p_frame
,
block_Duplicate
(
p_sys
->
p_ext
)
);
}
p_sys
->
i_seq_old
=
0
;
}
p_sys
->
b_gop
=
VLC_TRUE
;
}
CopyUntilNextStartCode
(
p_pack
,
p_sout_buffer
,
&
i_pos
);
}
}
if
(
i_pts
<=
0
&&
i_dts
<=
0
&&
p_pack
->
i_interpolated_dts
<=
0
)
{
msg_Dbg
(
p_pack
->
p_fifo
,
"need a starting pts/dts"
);
sout_BufferDelete
(
p_pack
->
p_sout_input
->
p_sout
,
p_sout_buffer
);
return
;
}
sout_BufferRealloc
(
p_pack
->
p_sout_input
->
p_sout
,
p_sout_buffer
,
i_pos
);
p_sout_buffer
->
i_size
=
i_pos
;
/* calculate frame duration */
if
(
p_pack
->
i_progressive_sequence
||
i_picture_structure
==
0x03
)
{
i_duration
=
(
mtime_t
)(
1000000
/
p_pack
->
d_frame_rate
);
}
else
{
i_duration
=
(
mtime_t
)(
1000000
/
p_pack
->
d_frame_rate
/
2
);
}
if
(
p_pack
->
i_progressive_sequence
)
{
if
(
i_top_field_first
==
0
&&
i_repeat_first_field
==
1
)
{
i_duration
=
2
*
i_duration
;
}
else
if
(
i_top_field_first
==
1
&&
i_repeat_first_field
==
1
)
{
i_duration
=
3
*
i_duration
;
}
}
else
{
if
(
i_picture_structure
==
0x03
)
{
if
(
i_progressive_frame
&&
i_repeat_first_field
)
else
if
(
p_frag
->
p_buffer
[
3
]
==
0xb3
)
{
i_duration
+=
i_duration
/
2
;
static
const
int
code_to_frame_rate
[
16
][
2
]
=
{
{
1
,
1
},
/* invalid */
{
24000
,
1001
},
{
24
,
1
},
{
25
,
1
},
{
30000
,
1001
},
{
30
,
1
},
{
50
,
1
},
{
60000
,
1001
},
{
60
,
1
},
{
1
,
1
},
{
1
,
1
},
{
1
,
1
},
{
1
,
1
},
/* invalid */
{
1
,
1
},
{
1
,
1
},
{
1
,
1
}
/* invalid */
};
/* sequence header */
if
(
p_sys
->
p_seq
)
{
block_Release
(
p_sys
->
p_seq
);
}
if
(
p_sys
->
p_ext
)
{
block_Release
(
p_sys
->
p_ext
);
p_sys
->
p_ext
=
NULL
;
}
p_sys
->
p_seq
=
block_Duplicate
(
p_frag
);
p_sys
->
i_seq_old
=
0
;
p_dec
->
fmt_out
.
video
.
i_width
=
(
p_frag
->
p_buffer
[
4
]
<<
4
)
|
(
p_frag
->
p_buffer
[
5
]
>>
4
);
p_dec
->
fmt_out
.
video
.
i_height
=
(
(
p_frag
->
p_buffer
[
5
]
&
0x0f
)
<<
8
)
|
p_frag
->
p_buffer
[
6
];
p_sys
->
i_frame_rate
=
code_to_frame_rate
[
p_frag
->
p_buffer
[
7
]
&
0x0f
][
0
];
p_sys
->
i_frame_rate_base
=
code_to_frame_rate
[
p_frag
->
p_buffer
[
7
]
&
0x0f
][
1
];
p_sys
->
b_seq_progressive
=
VLC_TRUE
;
p_sys
->
b_low_delay
=
VLC_TRUE
;
msg_Dbg
(
p_dec
,
"Size %dx%d fps=%.3f"
,
p_dec
->
fmt_out
.
video
.
i_width
,
p_dec
->
fmt_out
.
video
.
i_height
,
(
float
)
p_sys
->
i_frame_rate
/
(
float
)
p_sys
->
i_frame_rate_base
);
}
else
if
(
p_frag
->
p_buffer
[
3
]
==
0xb5
)
{
int
i_type
=
p_frag
->
p_buffer
[
4
]
>>
4
;
/* extention start code */
if
(
i_type
==
0x01
)
{
/* sequence extention */
if
(
p_sys
->
p_ext
)
{
block_Release
(
p_sys
->
p_ext
);
}
p_sys
->
p_ext
=
block_Duplicate
(
p_frag
);
if
(
p_frag
->
i_buffer
>=
10
)
{
p_sys
->
b_seq_progressive
=
p_frag
->
p_buffer
[
5
]
&
0x08
?
VLC_TRUE
:
VLC_FALSE
;
p_sys
->
b_low_delay
=
p_frag
->
p_buffer
[
9
]
&
0x80
?
VLC_TRUE
:
VLC_FALSE
;
}
}
else
if
(
i_type
==
0x08
)
{
/* picture extention */
p_sys
->
i_picture_structure
=
p_frag
->
p_buffer
[
6
]
&
0x03
;
p_sys
->
i_top_field_first
=
p_frag
->
p_buffer
[
7
]
>>
7
;
p_sys
->
i_repeat_first_field
=
(
p_frag
->
p_buffer
[
7
]
>>
1
)
&
0x01
;
p_sys
->
i_progressive_frame
=
p_frag
->
p_buffer
[
8
]
>>
7
;
}
}
else
if
(
p_frag
->
p_buffer
[
3
]
==
0x00
)
{
/* picture */
p_sys
->
i_seq_old
++
;
if
(
p_frag
->
i_buffer
>=
6
)
{
p_sys
->
i_temporal_ref
=
(
p_frag
->
p_buffer
[
4
]
<<
2
)
|
(
p_frag
->
p_buffer
[
5
]
>>
6
);
p_sys
->
i_picture_type
=
(
p_frag
->
p_buffer
[
5
]
>>
3
)
&
0x03
;
}
if
(
!
p_sys
->
b_frame_slice
)
{
p_sys
->
i_dts
=
p_block
->
i_dts
;
p_block
->
i_dts
=
0
;
p_sys
->
i_pts
=
p_block
->
i_pts
;
p_block
->
i_pts
=
0
;
}
}
else
if
(
p_frag
->
p_buffer
[
3
]
>=
0x01
&&
p_frag
->
p_buffer
[
3
]
<=
0xaf
)
{
/* Slice */
p_sys
->
b_frame_slice
=
VLC_TRUE
;
}
}
}
if
(
p_pack
->
i_low_delay
||
i_picture_coding_type
==
0x03
)
{
/* Trivial case (DTS == PTS) */
/* Correct interpolated dts when we receive a new pts/dts */
if
(
i_pts
>
0
)
p_pack
->
i_interpolated_dts
=
i_pts
;
if
(
i_dts
>
0
)
p_pack
->
i_interpolated_dts
=
i_dts
;
}
else
{
/* Correct interpolated dts when we receive a new pts/dts */
if
(
p_pack
->
i_last_ref_pts
)
p_pack
->
i_interpolated_dts
=
p_pack
->
i_last_ref_pts
;
if
(
i_dts
>
0
)
p_pack
->
i_interpolated_dts
=
i_dts
;
p_pack
->
i_last_ref_pts
=
i_pts
;
}
/* Don't even try to calculate the PTS unless it is given in the
* original stream */
p_sout_buffer
->
i_pts
=
i_pts
?
i_pts
:
-
1
;
p_sout_buffer
->
i_dts
=
p_pack
->
i_interpolated_dts
;
if
(
p_pack
->
i_low_delay
||
i_picture_coding_type
==
0x03
)
{
/* Trivial case (DTS == PTS) */
p_pack
->
i_interpolated_dts
+=
i_duration
;
}
else
{
p_pack
->
i_interpolated_dts
+=
p_pack
->
i_old_duration
;
p_pack
->
i_old_duration
=
i_duration
;
}
p_sout_buffer
->
i_length
=
p_pack
->
i_interpolated_dts
-
p_sout_buffer
->
i_dts
;
p_sout_buffer
->
i_bitrate
=
(
int
)(
8
*
i_pos
*
p_pack
->
d_frame_rate
);
#if 0
msg_Dbg( p_pack->p_fifo, "------------> dts=%lld pts=%lld duration=%lld",
p_sout_buffer->i_dts, p_sout_buffer->i_pts,
p_sout_buffer->i_length );
#endif
if
(
p_pack
->
b_expect_discontinuity
)
{
msg_Warn
(
p_pack
->
p_fifo
,
"discontinuity encountered, dropping a frame"
);
p_pack
->
b_expect_discontinuity
=
0
;
sout_BufferDelete
(
p_pack
->
p_sout_input
->
p_sout
,
p_sout_buffer
);
}
else
{
sout_InputSendBuffer
(
p_pack
->
p_sout_input
,
p_sout_buffer
);
}
}
/*****************************************************************************
* EndThread : packetizer thread destruction
*****************************************************************************/
static
void
EndThread
(
packetizer_t
*
p_pack
)
{
if
(
p_pack
->
p_sout_input
)
{
sout_InputDelete
(
p_pack
->
p_sout_input
);
/* Append the block */
block_ChainAppend
(
&
p_sys
->
p_frame
,
p_frag
);
}
p_sys
->
p_old
=
p_sys
->
p_start
;
p_sys
->
p_start
+=
4
;
}
}
/*****************************************************************************
* BitstreamCallback: Import parameters from the new data/PES packet
*****************************************************************************
* This function is called by input's NextDataPacket.
*****************************************************************************/
static
void
BitstreamCallback
(
bit_stream_t
*
p_bit_stream
,
vlc_bool_t
b_new_pes
)
static
int
mpgv_FindStartCode
(
uint8_t
**
pp_start
,
uint8_t
*
p_end
)
{
packetizer_t
*
p_pack
=
(
packetizer_t
*
)
p_bit_stream
->
p_callback_arg
;
uint8_t
*
p
=
*
pp_start
;
if
(
p_bit_stream
->
p_data
->
b_discard_payload
||
(
b_new_pes
&&
p_bit_stream
->
p_pes
->
b_discontinuity
)
)
for
(
p
=
*
pp_start
;
p
<
p_end
-
4
;
p
++
)
{
p_pack
->
b_expect_discontinuity
=
1
;
if
(
p
[
0
]
==
0
&&
p
[
1
]
==
0
&&
p
[
2
]
==
1
)
{
*
pp_start
=
p
;
return
VLC_SUCCESS
;
}
}
*
pp_start
=
p
;
return
VLC_EGENERIC
;
}
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