Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-1.1
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-1.1
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 @@
...
@@ -2,7 +2,7 @@
* mpegvideo.c
* mpegvideo.c
*****************************************************************************
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* 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>
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
* Eric Petit <titer@videolan.org>
...
@@ -39,537 +39,479 @@
...
@@ -39,537 +39,479 @@
/*****************************************************************************
/*****************************************************************************
* Preamble
* Preamble
*****************************************************************************/
*****************************************************************************/
#include <stdlib.h>
/* malloc(), free() */
#include <vlc/vlc.h>
#include <vlc/vlc.h>
#include <vlc/decoder.h>
#include <vlc/decoder.h>
#include <vlc/input.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
* Module descriptor
*****************************************************************************/
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
vlc_module_begin
();
vlc_module_begin
();
set_description
(
_
(
"MPEG-I/II video packetizer"
)
);
set_description
(
_
(
"MPEG-I/II video packetizer"
)
);
set_capability
(
"packetizer"
,
50
);
set_capability
(
"packetizer"
,
50
);
set_callbacks
(
Open
,
NULL
);
set_callbacks
(
Open
,
Close
);
vlc_module_end
();
vlc_module_end
();
/*****************************************************************************
/*****************************************************************************
* OpenDecoder: probe the packetizer and return score
* Local prototypes
*****************************************************************************
* Tries to launch a decoder and return score so that the interface is able
* to choose.
*****************************************************************************/
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
p_this
)
static
block_t
*
Packetize
(
decoder_t
*
,
block_t
**
);
{
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
if
(
p_dec
->
p_fifo
->
i_fourcc
!=
VLC_FOURCC
(
'm'
,
'p'
,
'g'
,
'v'
)
&&
static
int
mpgv_FindStartCode
(
uint8_t
**
pp_start
,
uint8_t
*
p_end
);
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
;
}
p_dec
->
pf_run
=
Run
;
struct
decoder_sys_t
return
VLC_SUCCESS
;
{
}
/* 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
;
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
int
b_error
;
decoder_sys_t
*
p_sys
;
msg_Info
(
p_fifo
,
"Running mpegvideo packetizer"
);
if
(
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
'm'
,
'p'
,
'g'
,
'1'
)
&&
if
(
!
(
p_pack
=
malloc
(
sizeof
(
packetizer_t
)
)
)
)
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"
);
return
VLC_EGENERIC
;
DecoderError
(
p_fifo
);
return
(
-
1
);
}
}
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
)
p_dec
->
p_sys
=
p_sys
=
malloc
(
sizeof
(
decoder_sys_t
)
);
{
DecoderError
(
p_fifo
);
return
(
-
1
);
}
while
(
(
!
p_pack
->
p_fifo
->
b_die
)
&&
(
!
p_pack
->
p_fifo
->
b_error
)
)
p_sys
->
p_seq
=
NULL
;
{
p_sys
->
p_ext
=
NULL
;
PacketizeThread
(
p_pack
);
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
)
)
p_sys
->
i_dts
=
0
;
{
p_sys
->
i_pts
=
0
;
DecoderError
(
p_pack
->
p_fifo
);
}
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
)
p_sys
->
i_temporal_ref
=
0
;
{
p_sys
->
i_picture_type
=
0
;
free
(
p_pack
);
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
)
p_sys
->
i_interpolated_dts
=
0
;
{
p_sys
->
i_old_duration
=
0
;
return
(
-
1
);
p_sys
->
i_last_ref_pts
=
0
;
}
return
(
0
)
;
return
VLC_SUCCESS
;
}
}
/*****************************************************************************
/*****************************************************************************
*
InitThread: initialize data before entering main loop
*
Close:
*****************************************************************************/
*****************************************************************************/
static
void
Close
(
vlc_object_t
*
p_this
)
static
int
InitThread
(
packetizer_t
*
p_pack
)
{
{
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
;
if
(
p_sys
->
p_seq
)
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
)
{
{
msg_Err
(
p_pack
->
p_fifo
,
"cannot initialize bitstream"
);
block_Release
(
p_sys
->
p_seq
);
return
-
1
;
}
}
if
(
p_sys
->
p_ext
)
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
{
{
p_sout_buffer
->
p_buffer
[(
*
pi_pos
)
++
]
=
block_Release
(
p_sys
->
p_ext
);
GetBits
(
&
p_pack
->
bit_stream
,
8
);
}
i_copy
++
;
if
(
p_sys
->
p_frame
)
{
if
(
*
pi_pos
+
2048
>
p_sout_buffer
->
i_buffer_size
)
block_Release
(
p_sys
->
p_frame
);
{
}
sout_BufferRealloc
(
p_pack
->
p_sout_input
->
p_sout
,
free
(
p_sys
->
p_buffer
);
p_sout_buffer
,
free
(
p_sys
);
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
);
}
}
/*****************************************************************************
/*****************************************************************************
* 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
;
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
vlc_bool_t
b_seen_slice
=
VLC_FALSE
;
block_t
*
p_chain_out
=
NULL
;
int32_t
i_pos
;
block_t
*
p_block
;
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
;
/* copy headers */
if
(
pp_block
==
NULL
||
*
pp_block
==
NULL
)
GetChunk
(
&
p_pack
->
bit_stream
,
p_temp
+
i_pos
,
7
);
i_pos
+=
7
;
{
return
NULL
;
}
p_block
=
*
pp_block
;
*
pp_block
=
NULL
;
/* intra_quantiser_matrix [non_intra_quantiser_matrix] */
if
(
p_block
->
b_discontinuity
)
if
(
ShowBits
(
&
p_pack
->
bit_stream
,
7
)
&
0x1
)
{
{
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
)
p_sys
->
i_buffer_size
+=
p_block
->
i_buffer
+
1024
;
{
p_sys
->
p_buffer
=
realloc
(
p_sys
->
p_buffer
,
p_sys
->
i_buffer_size
);
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
;
}
/* sequence_extension (10 bytes) */
if
(
p_sys
->
p_start
)
if
(
ShowBits
(
&
p_pack
->
bit_stream
,
32
)
!=
0x1B5
)
{
{
msg_Dbg
(
p_pack
->
p_fifo
,
"ARRGG no extension_start_code"
);
p_sys
->
p_start
=
p_sys
->
p_start
-
p_buffer
+
p_sys
->
p_buffer
;
p_pack
->
i_progressive_sequence
=
1
;
p_pack
->
i_low_delay
=
1
;
}
}
else
if
(
p_sys
->
p_old
)
{
{
GetChunk
(
&
p_pack
->
bit_stream
,
p_temp
+
i_pos
,
10
);
p_sys
->
p_old
=
p_sys
->
p_old
-
p_buffer
+
p_sys
->
p_buffer
;
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
;
}
}
/* remember sequence_header and sequence_extention */
}
memcpy
(
p_pack
->
p_sequence_header
,
p_temp
,
i_pos
);
memcpy
(
&
p_sys
->
p_buffer
[
p_sys
->
i_buffer
],
p_block
->
p_buffer
,
p_pack
->
i_sequence_header_length
=
i_pos
;
p_block
->
i_buffer
);
p_sys
->
i_buffer
+=
p_block
->
i_buffer
;
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
;
}
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
);
}
if
(
p_sys
->
i_buffer
>
10
*
1000000
)
else
{
{
p_sout_buffer
=
msg_Err
(
p_dec
,
"mmh reseting context"
);
sout_BufferNew
(
p_pack
->
p_sout_input
->
p_sout
,
100
*
1024
);
p_sys
->
i_buffer
=
0
;
i_pos
=
0
;
}
}
p_pack
->
i_last_sequence_header
++
;
/* Split data in block */
for
(
;;
)
for
(
;;
)
{
{
uint32_t
i_code
;
if
(
mpgv_FindStartCode
(
&
p_sys
->
p_start
,
&
p_sys
->
p_buffer
[
p_sys
->
i_buffer
]
)
)
if
(
p_pack
->
p_fifo
->
b_die
||
p_pack
->
p_fifo
->
b_error
)
{
{
break
;
block_Release
(
p_block
);
}
i_code
=
ShowBits
(
&
p_pack
->
bit_stream
,
32
);
if
(
b_seen_slice
&&
(
i_code
<
0x101
||
i_code
>
0x1af
)
)
{
break
;
}
if
(
i_code
==
0x1B8
)
/* GOP */
if
(
p_sys
->
p_seq
==
NULL
)
{
/* usefull for bad MPEG-1 : repeat the sequence_header
every second */
if
(
p_pack
->
i_last_sequence_header
>
(
int
)
p_pack
->
d_frame_rate
)
{
{
memcpy
(
p_sout_buffer
->
p_buffer
+
i_pos
,
block_ChainRelease
(
p_chain_out
);
p_pack
->
p_sequence_header
,
return
NULL
;
p_pack
->
i_sequence_header_length
);
i_pos
+=
p_pack
->
i_sequence_header_length
;
p_pack
->
i_last_sequence_header
=
0
;
}
}
p_sout_buffer
->
i_flags
|=
SOUT_BUFFER_FLAGS_GOP
;
return
p_chain_out
;
CopyUntilNextStartCode
(
p_pack
,
p_sout_buffer
,
&
i_pos
);
}
}
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
);
if
(
p_sys
->
p_old
)
}
else
if
(
i_code
==
0x1b5
)
{
{
/*
extention start code 32
*/
/*
Extract the data
*/
GetChunk
(
&
p_pack
->
bit_stream
,
int
i_frag
=
p_sys
->
p_start
-
p_sys
->
p_old
;
p_sout_buffer
->
p_buffer
+
i_pos
,
4
);
i_pos
+=
4
;
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 */
memmove
(
p_sys
->
p_buffer
,
&
p_sys
->
p_buffer
[
i_frag
],
p_sys
->
i_buffer
-
i_frag
);
/* 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
;
}
}
CopyUntilNextStartCode
(
p_pack
,
p_sout_buffer
,
&
i_pos
)
;
p_sys
->
i_buffer
-=
i_frag
;
}
p_sys
->
p_start
-=
i_frag
;
else
p_sys
->
p_old
-=
i_frag
;
{
if
(
i_code
>=
0x101
&&
i_code
<=
0x1af
)
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
);
else
if
(
p_frag
->
p_buffer
[
3
]
==
0xb3
)
}
}
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
)
{
{
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
);
}
}
/*****************************************************************************
/* Append the block */
* EndThread : packetizer thread destruction
block_ChainAppend
(
&
p_sys
->
p_frame
,
p_frag
);
*****************************************************************************/
}
static
void
EndThread
(
packetizer_t
*
p_pack
)
p_sys
->
p_old
=
p_sys
->
p_start
;
{
p_sys
->
p_start
+=
4
;
if
(
p_pack
->
p_sout_input
)
{
sout_InputDelete
(
p_pack
->
p_sout_input
);
}
}
}
}
/*****************************************************************************
static
int
mpgv_FindStartCode
(
uint8_t
**
pp_start
,
uint8_t
*
p_end
)
* 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
)
{
{
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
for
(
p
=
*
pp_start
;
p
<
p_end
-
4
;
p
++
)
||
(
b_new_pes
&&
p_bit_stream
->
p_pes
->
b_discontinuity
)
)
{
{
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