Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-2-2
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-2-2
Commits
1c2a95b8
Commit
1c2a95b8
authored
Jan 11, 2011
by
Anuradha Suraparaju
Committed by
Jean-Baptiste Kempf
Jan 13, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Dirac encoding support to VLC using the Schroedinger library.
Signed-off-by:
Jean-Baptiste Kempf
<
jb@videolan.org
>
parent
677f45de
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
745 additions
and
1 deletion
+745
-1
configure.ac
configure.ac
+1
-1
modules/codec/schroedinger.c
modules/codec/schroedinger.c
+744
-0
No files found.
configure.ac
View file @
1c2a95b8
...
...
@@ -2967,7 +2967,7 @@ PKG_ENABLE_MODULES_VLC([DIRAC], [], [dirac >= 0.10.0], [dirac encoder], [auto])
dnl
dnl schroedinger decoder plugin (for dirac format video)
dnl
PKG_ENABLE_MODULES_VLC([SCHROEDINGER], [], [schroedinger-1.0 >= 1.0.
6], [dirac de
coder using schroedinger], [auto])
PKG_ENABLE_MODULES_VLC([SCHROEDINGER], [], [schroedinger-1.0 >= 1.0.
10], [dirac decoder and en
coder using schroedinger], [auto])
dnl
dnl PNG decoder module
...
...
modules/codec/schroedinger.c
View file @
1c2a95b8
...
...
@@ -8,6 +8,7 @@
*
* Authors: Jonathan Rosser <jonathan.rosser@gmail.com>
* David Flynn <davidf at rd dot bbc.co.uk>
* Anuradha Suraparaju <asuraparaju at gmail dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -31,6 +32,8 @@
# include "config.h"
#endif
#include <assert.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_codec.h>
...
...
@@ -43,6 +46,27 @@
*****************************************************************************/
static
int
OpenDecoder
(
vlc_object_t
*
);
static
void
CloseDecoder
(
vlc_object_t
*
);
static
int
OpenEncoder
(
vlc_object_t
*
);
static
void
CloseEncoder
(
vlc_object_t
*
);
#define ENC_CFG_PREFIX "sout-schro-"
#define ENC_CHROMAFMT "chroma_fmt"
#define ENC_CHROMAFMT_TEXT N_("Chroma format")
#define ENC_CHROMAFMT_LONGTEXT N_("Picking chroma format will force a " \
"conversion of the video into that format")
static
const
char
*
const
enc_chromafmt_list
[]
=
{
"420"
,
"422"
,
"444"
};
static
const
char
*
const
enc_chromafmt_list_text
[]
=
{
N_
(
"4:2:0"
),
N_
(
"4:2:2"
),
N_
(
"4:4:4"
)
};
#define ENC_CODINGMODE "auto_coding_mode"
#define ENC_CODINGMODE_TEXT N_("Automate picture coding mode")
#define ENC_CODINGMODE_LONGTEXT N_("Use the input picture to determine how to" \
" code it - interlaced or progressive")
static
const
char
**
ppsz_enc_options
=
NULL
;
vlc_module_begin
()
set_category
(
CAT_INPUT
)
...
...
@@ -51,6 +75,66 @@ vlc_module_begin ()
set_capability
(
"decoder"
,
200
)
set_callbacks
(
OpenDecoder
,
CloseDecoder
)
add_shortcut
(
"schroedinger"
)
add_submodule
()
set_description
(
N_
(
"Dirac video encoder using libschroedinger"
)
)
set_capability
(
"encoder"
,
110
)
set_callbacks
(
OpenEncoder
,
CloseEncoder
)
add_shortcut
(
"schroedinger"
,
"schro"
)
int
i_numopts
=
schro_encoder_get_n_settings
();
/* Allocate for schro encoder options + chroma format + coding mode
+ null */
ppsz_enc_options
=
(
const
char
**
)
malloc
(
sizeof
(
char
*
)
*
(
i_numopts
+
3
)
);
if
(
unlikely
(
ppsz_enc_options
==
NULL
)
)
return
VLC_ENOMEM
;
for
(
int
i
=
0
;
i
<
i_numopts
;
++
i
)
{
const
SchroEncoderSetting
*
p_setting
=
schro_encoder_get_setting_info
(
i
);
bool
b_advanced
=
(
strlen
(
p_setting
->
name
)
>
6
&&
!
strncmp
(
p_setting
->
name
,
"magic_ "
,
6
)
);
char
*
p_cfg_setting_name
=
malloc
(
strlen
(
ENC_CFG_PREFIX
)
+
strlen
(
p_setting
->
name
)
+
1
);
if
(
unlikely
(
p_cfg_setting_name
==
NULL
)
)
return
VLC_ENOMEM
;
strcpy
(
p_cfg_setting_name
,
ENC_CFG_PREFIX
);
strcat
(
p_cfg_setting_name
,
p_setting
->
name
);
ppsz_enc_options
[
i
]
=
strdup
(
p_setting
->
name
);
switch
(
p_setting
->
type
)
{
case
SCHRO_ENCODER_SETTING_TYPE_BOOLEAN
:
add_bool
(
p_cfg_setting_name
,
p_setting
->
default_value
,
p_setting
->
name
,
p_setting
->
name
,
b_advanced
);
break
;
case
SCHRO_ENCODER_SETTING_TYPE_INT
:
add_integer
(
p_cfg_setting_name
,
p_setting
->
default_value
,
p_setting
->
name
,
p_setting
->
name
,
b_advanced
);
change_integer_range
(
p_setting
->
min
,
p_setting
->
max
);
break
;
case
SCHRO_ENCODER_SETTING_TYPE_DOUBLE
:
add_float
(
p_cfg_setting_name
,
p_setting
->
default_value
,
p_setting
->
name
,
p_setting
->
name
,
b_advanced
);
change_float_range
(
p_setting
->
min
,
p_setting
->
max
);
break
;
case
SCHRO_ENCODER_SETTING_TYPE_ENUM
:
add_string
(
p_cfg_setting_name
,
p_setting
->
enum_list
[(
int
)
p_setting
->
default_value
],
p_setting
->
name
,
p_setting
->
name
,
b_advanced
);
vlc_config_set
(
p_config
,
VLC_CONFIG_LIST
,
(
int
)(
p_setting
->
max
-
p_setting
->
min
+
1
),
p_setting
->
enum_list
,
p_setting
->
enum_list
,
0
);
break
;
default:
break
;
}
free
(
p_cfg_setting_name
);
}
ppsz_enc_options
[
i_numopts
]
=
strdup
(
ENC_CHROMAFMT
);
add_string
(
ENC_CFG_PREFIX
ENC_CHROMAFMT
,
"420"
,
ENC_CHROMAFMT_TEXT
,
ENC_CHROMAFMT_LONGTEXT
,
false
)
change_string_list
(
enc_chromafmt_list
,
enc_chromafmt_list_text
,
0
);
ppsz_enc_options
[
i_numopts
+
1
]
=
strdup
(
ENC_CODINGMODE
);
add_bool
(
ENC_CFG_PREFIX
ENC_CODINGMODE
,
true
,
ENC_CODINGMODE_TEXT
,
ENC_CODINGMODE_LONGTEXT
,
false
)
ppsz_enc_options
[
i_numopts
+
2
]
=
NULL
;
vlc_module_end
()
/*****************************************************************************
...
...
@@ -393,3 +477,663 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
}
}
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static
block_t
*
Encode
(
encoder_t
*
p_enc
,
picture_t
*
p_pict
);
/*****************************************************************************
* picture_pts_t : store pts alongside picture number, not carried through
* encoder
*****************************************************************************/
struct
picture_pts_t
{
bool
b_empty
;
/* entry is invalid */
uint32_t
u_pnum
;
/* dirac picture number */
mtime_t
i_pts
;
/* associated pts */
};
/*****************************************************************************
* encoder_sys_t : Schroedinger encoder descriptor
*****************************************************************************/
#define SCHRO_PTS_TLB_SIZE 256
struct
encoder_sys_t
{
/*
* Schro properties
*/
SchroEncoder
*
p_schro
;
SchroVideoFormat
*
p_format
;
int
started
;
bool
b_auto_field_coding
;
uint32_t
i_input_picnum
;
block_fifo_t
*
p_dts_fifo
;
block_t
*
p_chain
;
struct
picture_pts_t
pts_tlb
[
SCHRO_PTS_TLB_SIZE
];
mtime_t
i_pts_offset
;
mtime_t
i_field_time
;
bool
b_eos_signalled
;
bool
b_eos_pulled
;
};
static
struct
{
unsigned
int
i_height
;
int
i_approx_fps
;
SchroVideoFormatEnum
i_vf
;
}
schro_format_guess
[]
=
{
/* Important: Keep this list ordered in ascending picture height */
{
1
,
0
,
SCHRO_VIDEO_FORMAT_CUSTOM
},
{
120
,
15
,
SCHRO_VIDEO_FORMAT_QSIF
},
{
144
,
12
,
SCHRO_VIDEO_FORMAT_QCIF
},
{
240
,
15
,
SCHRO_VIDEO_FORMAT_SIF
},
{
288
,
12
,
SCHRO_VIDEO_FORMAT_CIF
},
{
480
,
30
,
SCHRO_VIDEO_FORMAT_SD480I_60
},
{
480
,
15
,
SCHRO_VIDEO_FORMAT_4SIF
},
{
576
,
12
,
SCHRO_VIDEO_FORMAT_4CIF
},
{
576
,
25
,
SCHRO_VIDEO_FORMAT_SD576I_50
},
{
720
,
50
,
SCHRO_VIDEO_FORMAT_HD720P_50
},
{
720
,
60
,
SCHRO_VIDEO_FORMAT_HD720P_60
},
{
1080
,
24
,
SCHRO_VIDEO_FORMAT_DC2K_24
},
{
1080
,
25
,
SCHRO_VIDEO_FORMAT_HD1080I_50
},
{
1080
,
30
,
SCHRO_VIDEO_FORMAT_HD1080I_60
},
{
1080
,
50
,
SCHRO_VIDEO_FORMAT_HD1080P_50
},
{
1080
,
60
,
SCHRO_VIDEO_FORMAT_HD1080P_60
},
{
2160
,
24
,
SCHRO_VIDEO_FORMAT_DC4K_24
},
{
0
,
0
,
0
},
};
/*****************************************************************************
* ResetPTStlb: Purge all entries in @p_enc@'s PTS-tlb
*****************************************************************************/
static
void
ResetPTStlb
(
encoder_t
*
p_enc
)
{
encoder_sys_t
*
p_sys
=
p_enc
->
p_sys
;
for
(
int
i
=
0
;
i
<
SCHRO_PTS_TLB_SIZE
;
i
++
)
{
p_sys
->
pts_tlb
[
i
].
b_empty
=
true
;
}
}
/*****************************************************************************
* StorePicturePTS: Store the PTS value for a particular picture number
*****************************************************************************/
static
void
StorePicturePTS
(
encoder_t
*
p_enc
,
uint32_t
u_pnum
,
mtime_t
i_pts
)
{
encoder_sys_t
*
p_sys
=
p_enc
->
p_sys
;
for
(
int
i
=
0
;
i
<
SCHRO_PTS_TLB_SIZE
;
i
++
)
{
if
(
p_sys
->
pts_tlb
[
i
].
b_empty
)
{
p_sys
->
pts_tlb
[
i
].
u_pnum
=
u_pnum
;
p_sys
->
pts_tlb
[
i
].
i_pts
=
i_pts
;
p_sys
->
pts_tlb
[
i
].
b_empty
=
false
;
return
;
}
}
msg_Err
(
p_enc
,
"Could not store PTS %"
PRId64
" for frame %u"
,
i_pts
,
u_pnum
);
}
/*****************************************************************************
* GetPicturePTS: Retrieve the PTS value for a particular picture number
*****************************************************************************/
static
mtime_t
GetPicturePTS
(
encoder_t
*
p_enc
,
uint32_t
u_pnum
)
{
encoder_sys_t
*
p_sys
=
p_enc
->
p_sys
;
for
(
int
i
=
0
;
i
<
SCHRO_PTS_TLB_SIZE
;
i
++
)
{
if
(
!
p_sys
->
pts_tlb
[
i
].
b_empty
&&
p_sys
->
pts_tlb
[
i
].
u_pnum
==
u_pnum
)
{
p_sys
->
pts_tlb
[
i
].
b_empty
=
true
;
return
p_sys
->
pts_tlb
[
i
].
i_pts
;
}
}
msg_Err
(
p_enc
,
"Could not retrieve PTS for picture %u"
,
u_pnum
);
return
0
;
}
static
inline
bool
SchroSetEnum
(
const
encoder_t
*
p_enc
,
const
SchroEncoderSetting
*
p_setting
,
const
char
*
psz_value
)
{
encoder_sys_t
*
p_sys
=
p_enc
->
p_sys
;
if
(
psz_value
&&
p_setting
&&
p_setting
->
type
==
SCHRO_ENCODER_SETTING_TYPE_ENUM
)
{
int
i_index
=
-
1
;
int
i_list_size
=
p_setting
->
max
-
p_setting
->
min
+
1
;
for
(
int
i
=
0
;
i
<
i_list_size
;
++
i
)
{
if
(
strcmp
(
p_setting
->
enum_list
[
i
],
psz_value
)
)
continue
;
i_index
=
p_setting
->
min
+
i
;
schro_encoder_setting_set_double
(
p_sys
->
p_schro
,
p_setting
->
name
,
i_index
);
return
true
;
}
if
(
i_index
==
-
1
)
{
msg_Err
(
p_enc
,
"Invalid %s: %s"
,
p_setting
->
name
,
psz_value
);
}
}
return
false
;
}
static
bool
SetEncChromaFormat
(
encoder_t
*
p_enc
,
uint32_t
i_codec
)
{
encoder_sys_t
*
p_sys
=
p_enc
->
p_sys
;
switch
(
i_codec
)
{
case
VLC_CODEC_I420
:
p_enc
->
fmt_in
.
i_codec
=
i_codec
;
p_enc
->
fmt_in
.
video
.
i_bits_per_pixel
=
12
;
p_sys
->
p_format
->
chroma_format
=
SCHRO_CHROMA_420
;
break
;
case
VLC_CODEC_I422
:
p_enc
->
fmt_in
.
i_codec
=
i_codec
;
p_enc
->
fmt_in
.
video
.
i_bits_per_pixel
=
16
;
p_sys
->
p_format
->
chroma_format
=
SCHRO_CHROMA_422
;
break
;
case
VLC_CODEC_I444
:
p_enc
->
fmt_in
.
i_codec
=
i_codec
;
p_enc
->
fmt_in
.
video
.
i_bits_per_pixel
=
24
;
p_sys
->
p_format
->
chroma_format
=
SCHRO_CHROMA_444
;
break
;
default:
return
false
;
}
return
true
;
}
/*****************************************************************************
* OpenEncoder: probe the encoder and return score
*****************************************************************************/
static
int
OpenEncoder
(
vlc_object_t
*
p_this
)
{
encoder_t
*
p_enc
=
(
encoder_t
*
)
p_this
;
encoder_sys_t
*
p_sys
=
p_enc
->
p_sys
;
int
i_tmp
;
float
f_tmp
;
bool
b_tmp
;
char
*
psz_tmp
;
if
(
p_enc
->
fmt_out
.
i_codec
!=
VLC_CODEC_DIRAC
&&
!
p_enc
->
b_force
)
{
return
VLC_EGENERIC
;
}
if
(
!
p_enc
->
fmt_in
.
video
.
i_frame_rate
||
!
p_enc
->
fmt_in
.
video
.
i_frame_rate_base
||
!
p_enc
->
fmt_in
.
video
.
i_height
||
!
p_enc
->
fmt_in
.
video
.
i_width
)
{
msg_Err
(
p_enc
,
"Framerate and picture dimensions must be non-zero"
);
return
VLC_EGENERIC
;
}
/* Allocate the memory needed to store the decoder's structure */
if
(
(
p_sys
=
calloc
(
1
,
sizeof
(
*
p_sys
)
)
)
==
NULL
)
return
VLC_ENOMEM
;
p_enc
->
p_sys
=
p_sys
;
p_enc
->
pf_encode_video
=
Encode
;
p_enc
->
fmt_out
.
i_codec
=
VLC_CODEC_DIRAC
;
p_enc
->
fmt_out
.
i_cat
=
VIDEO_ES
;
if
(
(
p_sys
->
p_dts_fifo
=
block_FifoNew
()
)
==
NULL
)
{
CloseEncoder
(
p_this
);
return
VLC_ENOMEM
;
}
ResetPTStlb
(
p_enc
);
/* guess the video format based upon number of lines and picture height */
int
i
=
0
;
SchroVideoFormatEnum
guessed_video_fmt
=
SCHRO_VIDEO_FORMAT_CUSTOM
;
/* Pick the dirac_video_format in this order of preference:
* 1. an exact match in frame height and an approximate fps match
* 2. the previous preset with a smaller number of lines.
*/
do
{
if
(
schro_format_guess
[
i
].
i_height
>
p_enc
->
fmt_in
.
video
.
i_height
)
{
guessed_video_fmt
=
schro_format_guess
[
i
-
1
].
i_vf
;
break
;
}
if
(
schro_format_guess
[
i
].
i_height
!=
p_enc
->
fmt_in
.
video
.
i_height
)
continue
;
int
src_fps
=
p_enc
->
fmt_in
.
video
.
i_frame_rate
/
p_enc
->
fmt_in
.
video
.
i_frame_rate_base
;
int
delta_fps
=
abs
(
schro_format_guess
[
i
].
i_approx_fps
-
src_fps
);
if
(
delta_fps
>
2
)
continue
;
guessed_video_fmt
=
schro_format_guess
[
i
].
i_vf
;
break
;
}
while
(
schro_format_guess
[
++
i
].
i_height
);
schro_init
();
p_sys
->
p_schro
=
schro_encoder_new
();
if
(
!
p_sys
->
p_schro
)
{
msg_Err
(
p_enc
,
"Failed to initialize libschroedinger encoder"
);
return
VLC_EGENERIC
;
}
schro_encoder_set_packet_assembly
(
p_sys
->
p_schro
,
true
);
if
(
!
(
p_sys
->
p_format
=
schro_encoder_get_video_format
(
p_sys
->
p_schro
)
)
)
{
msg_Err
(
p_enc
,
"Failed to get Schroedigner video format"
);
schro_encoder_free
(
p_sys
->
p_schro
);
return
VLC_EGENERIC
;
}
/* initialise the video format parameters to the guessed format */
schro_video_format_set_std_video_format
(
p_sys
->
p_format
,
guessed_video_fmt
);
/* constants set from the input video format */
p_sys
->
p_format
->
width
=
p_enc
->
fmt_in
.
video
.
i_width
;
p_sys
->
p_format
->
height
=
p_enc
->
fmt_in
.
video
.
i_height
;
p_sys
->
p_format
->
frame_rate_numerator
=
p_enc
->
fmt_in
.
video
.
i_frame_rate
;
p_sys
->
p_format
->
frame_rate_denominator
=
p_enc
->
fmt_in
.
video
.
i_frame_rate_base
;
unsigned
u_asr_num
,
u_asr_den
;
vlc_ureduce
(
&
u_asr_num
,
&
u_asr_den
,
p_enc
->
fmt_in
.
video
.
i_sar_num
,
p_enc
->
fmt_in
.
video
.
i_sar_den
,
0
);
p_sys
->
p_format
->
aspect_ratio_numerator
=
u_asr_num
;
p_sys
->
p_format
->
aspect_ratio_denominator
=
u_asr_den
;
config_ChainParse
(
p_enc
,
ENC_CFG_PREFIX
,
ppsz_enc_options
,
p_enc
->
p_cfg
);
int
i_numopts
=
schro_encoder_get_n_settings
();
for
(
int
i
=
0
;
i
<
i_numopts
;
++
i
)
{
const
SchroEncoderSetting
*
p_setting
=
schro_encoder_get_setting_info
(
i
);
char
*
p_cfg_setting_name
=
malloc
(
strlen
(
ENC_CFG_PREFIX
)
+
strlen
(
p_setting
->
name
)
+
1
);
if
(
unlikely
(
p_cfg_setting_name
==
NULL
)
)
return
VLC_ENOMEM
;
strcpy
(
p_cfg_setting_name
,
ENC_CFG_PREFIX
);
strcat
(
p_cfg_setting_name
,
p_setting
->
name
);
switch
(
p_setting
->
type
)
{
case
SCHRO_ENCODER_SETTING_TYPE_BOOLEAN
:
schro_encoder_setting_set_double
(
p_sys
->
p_schro
,
p_setting
->
name
,
var_GetBool
(
p_enc
,
p_cfg_setting_name
)
);
break
;
case
SCHRO_ENCODER_SETTING_TYPE_INT
:
i_tmp
=
var_GetInteger
(
p_enc
,
p_cfg_setting_name
);
schro_encoder_setting_set_double
(
p_sys
->
p_schro
,
p_setting
->
name
,
i_tmp
);
/* A kludge to set bitrate to the value in sout-transcode-vb */
if
(
!
strcmp
(
p_setting
->
name
,
"bitrate"
)
)
{
if
(
i_tmp
==
p_setting
->
default_value
)
schro_encoder_setting_set_double
(
p_sys
->
p_schro
,
p_setting
->
name
,
p_enc
->
fmt_out
.
i_bitrate
);
p_enc
->
fmt_out
.
i_bitrate
=
schro_encoder_setting_get_double
(
p_sys
->
p_schro
,
p_setting
->
name
);
}
break
;
case
SCHRO_ENCODER_SETTING_TYPE_DOUBLE
:
f_tmp
=
var_GetFloat
(
p_enc
,
p_cfg_setting_name
);
if
(
f_tmp
>=
0
.
0
)
schro_encoder_setting_set_double
(
p_sys
->
p_schro
,
p_setting
->
name
,
f_tmp
);
break
;
case
SCHRO_ENCODER_SETTING_TYPE_ENUM
:
psz_tmp
=
var_GetString
(
p_enc
,
p_cfg_setting_name
);
if
(
!
psz_tmp
)
goto
error
;
else
if
(
*
psz_tmp
!=
'\0'
)
{
if
(
!
SchroSetEnum
(
p_enc
,
p_setting
,
psz_tmp
)
)
{
free
(
psz_tmp
);
goto
error
;
}
}
free
(
psz_tmp
);
break
;
default:
break
;
}
free
(
p_cfg_setting_name
);
}
psz_tmp
=
var_GetString
(
p_enc
,
ENC_CFG_PREFIX
ENC_CHROMAFMT
);
if
(
!
psz_tmp
)
goto
error
;
else
{
uint32_t
i_codec
;
if
(
!
strcmp
(
psz_tmp
,
"420"
)
)
{
i_codec
=
VLC_CODEC_I420
;
}
else
if
(
!
strcmp
(
psz_tmp
,
"422"
)
)
{
i_codec
=
VLC_CODEC_I422
;
}
else
if
(
!
strcmp
(
psz_tmp
,
"444"
)
)
{
i_codec
=
VLC_CODEC_I444
;
}
else
{
msg_Err
(
p_enc
,
"Invalid chroma format: %s"
,
psz_tmp
);
free
(
psz_tmp
);
goto
error
;
}
SetEncChromaFormat
(
p_enc
,
i_codec
);
}
free
(
psz_tmp
);
b_tmp
=
var_GetBool
(
p_enc
,
ENC_CFG_PREFIX
ENC_CODINGMODE
);
if
(
b_tmp
==
true
)
p_sys
->
b_auto_field_coding
=
true
;
else
p_sys
->
b_auto_field_coding
=
false
;
p_sys
->
started
=
0
;
return
VLC_SUCCESS
;
error:
CloseEncoder
(
p_this
);
return
VLC_EGENERIC
;
}
struct
enc_picture_free_t
{
picture_t
*
p_pic
;
encoder_t
*
p_enc
;
};
/*****************************************************************************
* EncSchroFrameFree: schro_frame callback to release the associated picture_t
* When schro_encoder_reset() is called there will be pictures in the
* encoding pipeline that need to be released rather than displayed.
*****************************************************************************/
static
void
EncSchroFrameFree
(
SchroFrame
*
frame
,
void
*
priv
)
{
struct
enc_picture_free_t
*
p_free
=
priv
;
if
(
!
p_free
)
return
;
picture_Release
(
p_free
->
p_pic
);
free
(
p_free
);
(
void
)
frame
;
}
/*****************************************************************************
* CreateSchroFrameFromPic: wrap a picture_t in a SchroFrame
*****************************************************************************/
static
SchroFrame
*
CreateSchroFrameFromInputPic
(
encoder_t
*
p_enc
,
picture_t
*
p_pic
)
{
encoder_sys_t
*
p_sys
=
p_enc
->
p_sys
;
SchroFrame
*
p_schroframe
=
schro_frame_new
();
struct
enc_picture_free_t
*
p_free
;
if
(
!
p_schroframe
)
return
NULL
;
if
(
!
p_pic
)
return
NULL
;
p_schroframe
->
format
=
SCHRO_FRAME_FORMAT_U8_420
;
if
(
p_sys
->
p_format
->
chroma_format
==
SCHRO_CHROMA_422
)
{
p_schroframe
->
format
=
SCHRO_FRAME_FORMAT_U8_422
;
}
else
if
(
p_sys
->
p_format
->
chroma_format
==
SCHRO_CHROMA_444
)
{
p_schroframe
->
format
=
SCHRO_FRAME_FORMAT_U8_444
;
}
p_schroframe
->
width
=
p_sys
->
p_format
->
width
;
p_schroframe
->
height
=
p_sys
->
p_format
->
height
;
p_free
=
malloc
(
sizeof
(
*
p_free
)
);
if
(
unlikely
(
p_free
==
NULL
)
)
{
schro_frame_unref
(
p_schroframe
);
return
NULL
;
}
p_free
->
p_pic
=
p_pic
;
p_free
->
p_enc
=
p_enc
;
schro_frame_set_free_callback
(
p_schroframe
,
EncSchroFrameFree
,
p_free
);
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
p_schroframe
->
components
[
i
].
width
=
p_pic
->
p
[
i
].
i_visible_pitch
;
p_schroframe
->
components
[
i
].
stride
=
p_pic
->
p
[
i
].
i_pitch
;
p_schroframe
->
components
[
i
].
height
=
p_pic
->
p
[
i
].
i_visible_lines
;
p_schroframe
->
components
[
i
].
length
=
p_pic
->
p
[
i
].
i_pitch
*
p_pic
->
p
[
i
].
i_lines
;
p_schroframe
->
components
[
i
].
data
=
p_pic
->
p
[
i
].
p_pixels
;
if
(
i
!=
0
)
{
p_schroframe
->
components
[
i
].
v_shift
=
SCHRO_FRAME_FORMAT_V_SHIFT
(
p_schroframe
->
format
);
p_schroframe
->
components
[
i
].
h_shift
=
SCHRO_FRAME_FORMAT_H_SHIFT
(
p_schroframe
->
format
);
}
}
return
p_schroframe
;
}
/* Attempt to find dirac picture number in an encapsulation unit */
static
int
ReadDiracPictureNumber
(
uint32_t
*
p_picnum
,
block_t
*
p_block
)
{
uint32_t
u_pos
=
4
;
/* protect against falling off the edge */
while
(
u_pos
+
13
<
p_block
->
i_buffer
)
{
/* find the picture startcode */
if
(
p_block
->
p_buffer
[
u_pos
]
&
0x08
)
{
*
p_picnum
=
GetDWBE
(
p_block
->
p_buffer
+
u_pos
+
9
);
return
1
;
}
/* skip to the next dirac data unit */
uint32_t
u_npo
=
GetDWBE
(
p_block
->
p_buffer
+
u_pos
+
1
);
assert
(
u_npo
<=
UINT32_MAX
-
u_pos
);
if
(
u_npo
==
0
)
u_npo
=
13
;
u_pos
+=
u_npo
;
}
return
0
;
}
static
block_t
*
Encode
(
encoder_t
*
p_enc
,
picture_t
*
p_pic
)
{
encoder_sys_t
*
p_sys
=
p_enc
->
p_sys
;
block_t
*
p_block
,
*
p_output_chain
=
NULL
;
SchroFrame
*
p_frame
;
bool
b_go
=
true
;
if
(
!
p_pic
)
{
if
(
!
p_sys
->
started
||
p_sys
->
b_eos_pulled
)
return
NULL
;
if
(
!
p_sys
->
b_eos_signalled
)
{
p_sys
->
b_eos_signalled
=
1
;
schro_encoder_end_of_stream
(
p_sys
->
p_schro
);
}
}
else
{
/* we only know if the sequence is interlaced when the first
* picture arrives, so final setup is done here */
/* XXX todo, detect change of interlace */
p_sys
->
p_format
->
interlaced
=
!
p_pic
->
b_progressive
;
p_sys
->
p_format
->
top_field_first
=
p_pic
->
b_top_field_first
;
if
(
p_sys
->
b_auto_field_coding
)
schro_encoder_setting_set_double
(
p_sys
->
p_schro
,
"interlaced_coding"
,
!
p_pic
->
b_progressive
);
}
if
(
!
p_sys
->
started
)
{
date_t
date
;
if
(
p_pic
->
format
.
i_chroma
!=
p_enc
->
fmt_in
.
i_codec
)
{
char
chroma_in
[
5
],
chroma_out
[
5
];
vlc_fourcc_to_char
(
p_pic
->
format
.
i_chroma
,
chroma_in
);
chroma_in
[
4
]
=
'\0'
;
chroma_out
[
4
]
=
'\0'
;
vlc_fourcc_to_char
(
p_enc
->
fmt_in
.
i_codec
,
chroma_out
);
msg_Warn
(
p_enc
,
"Resetting chroma from %s to %s"
,
chroma_out
,
chroma_in
);
if
(
!
SetEncChromaFormat
(
p_enc
,
p_pic
->
format
.
i_chroma
)
)
{
msg_Err
(
p_enc
,
"Could not reset chroma format to %s"
,
chroma_in
);
return
NULL
;
}
}
date_Init
(
&
date
,
p_enc
->
fmt_in
.
video
.
i_frame_rate
,
p_enc
->
fmt_in
.
video
.
i_frame_rate_base
);
/* FIXME - Unlike dirac-research codec Schro doesn't have a function that returns the delay in pics yet.
* Use a default of 1
*/
date_Increment
(
&
date
,
1
);
p_sys
->
i_pts_offset
=
date_Get
(
&
date
);
if
(
schro_encoder_setting_get_double
(
p_sys
->
p_schro
,
"interlaced_coding"
)
>
0
.
0
)
{
date_Set
(
&
date
,
0
);
date_Increment
(
&
date
,
1
);
p_sys
->
i_field_time
=
date_Get
(
&
date
)
/
2
;
}
schro_video_format_set_std_signal_range
(
p_sys
->
p_format
,
SCHRO_SIGNAL_RANGE_8BIT_VIDEO
);
schro_encoder_set_video_format
(
p_sys
->
p_schro
,
p_sys
->
p_format
);
schro_encoder_start
(
p_sys
->
p_schro
);
p_sys
->
started
=
1
;
}
if
(
!
p_sys
->
b_eos_signalled
)
{
/* create a schro frame from the input pic and load */
/* Increase ref count by 1 so that the picture is not freed until
Schro finishes with it */
picture_Hold
(
p_pic
);
p_frame
=
CreateSchroFrameFromInputPic
(
p_enc
,
p_pic
);
if
(
!
p_frame
)
return
NULL
;
schro_encoder_push_frame
(
p_sys
->
p_schro
,
p_frame
);
/* store pts in a lookaside buffer, so that the same pts may
* be used for the picture in coded order */
StorePicturePTS
(
p_enc
,
p_sys
->
i_input_picnum
,
p_pic
->
date
);
p_sys
->
i_input_picnum
++
;
/* store dts in a queue, so that they appear in order in
* coded order */
p_block
=
block_New
(
p_enc
,
1
);
if
(
!
p_block
)
return
NULL
;
p_block
->
i_dts
=
p_pic
->
date
-
p_sys
->
i_pts_offset
;
block_FifoPut
(
p_sys
->
p_dts_fifo
,
p_block
);
p_block
=
NULL
;
/* for field coding mode, insert an extra value into both the
* pts lookaside buffer and dts queue, offset to correspond
* to a one field delay. */
if
(
schro_encoder_setting_get_double
(
p_sys
->
p_schro
,
"interlaced_coding"
)
>
0
.
0
)
{
StorePicturePTS
(
p_enc
,
p_sys
->
i_input_picnum
,
p_pic
->
date
+
p_sys
->
i_field_time
);
p_sys
->
i_input_picnum
++
;
p_block
=
block_New
(
p_enc
,
1
);
if
(
!
p_block
)
return
NULL
;
p_block
->
i_dts
=
p_pic
->
date
-
p_sys
->
i_pts_offset
+
p_sys
->
i_field_time
;
block_FifoPut
(
p_sys
->
p_dts_fifo
,
p_block
);
p_block
=
NULL
;
}
}
do
{
SchroStateEnum
state
;
state
=
schro_encoder_wait
(
p_sys
->
p_schro
);
switch
(
state
)
{
case
SCHRO_STATE_NEED_FRAME
:
b_go
=
false
;
break
;
case
SCHRO_STATE_AGAIN
:
break
;
case
SCHRO_STATE_END_OF_STREAM
:
p_sys
->
b_eos_pulled
=
1
;
b_go
=
false
;
break
;
case
SCHRO_STATE_HAVE_BUFFER
:
{
SchroBuffer
*
p_enc_buf
;
uint32_t
u_pic_num
;
int
i_presentation_frame
;
p_enc_buf
=
schro_encoder_pull
(
p_sys
->
p_schro
,
&
i_presentation_frame
);
p_block
=
block_New
(
p_enc
,
p_enc_buf
->
length
);
if
(
!
p_block
)
return
NULL
;
memcpy
(
p_block
->
p_buffer
,
p_enc_buf
->
data
,
p_enc_buf
->
length
);
schro_buffer_unref
(
p_enc_buf
);
/* Presence of a Sequence header indicates a seek point */
if
(
0
==
p_block
->
p_buffer
[
4
]
)
{
p_block
->
i_flags
|=
BLOCK_FLAG_TYPE_I
;
if
(
!
p_enc
->
fmt_out
.
p_extra
)
{
const
uint8_t
eos
[]
=
{
'B'
,
'B'
,
'C'
,
'D'
,
0x10
,
0
,
0
,
0
,
13
,
0
,
0
,
0
,
0
};
uint32_t
len
=
GetDWBE
(
p_block
->
p_buffer
+
5
);
/* if it hasn't been done so far, stash a copy of the
* sequence header for muxers such as ogg */
/* The OggDirac spec advises that a Dirac EOS DataUnit
* is appended to the sequence header to allow guard
* against poor streaming servers */
/* XXX, should this be done using the packetizer ? */
p_enc
->
fmt_out
.
p_extra
=
malloc
(
len
+
sizeof
(
eos
)
);
if
(
!
p_enc
->
fmt_out
.
p_extra
)
return
NULL
;
memcpy
(
p_enc
->
fmt_out
.
p_extra
,
p_block
->
p_buffer
,
len
);
memcpy
(
(
uint8_t
*
)
p_enc
->
fmt_out
.
p_extra
+
len
,
eos
,
sizeof
(
eos
)
);
SetDWBE
(
(
uint8_t
*
)
p_enc
->
fmt_out
.
p_extra
+
len
+
10
,
len
);
p_enc
->
fmt_out
.
i_extra
=
len
+
sizeof
(
eos
);
}
}
if
(
ReadDiracPictureNumber
(
&
u_pic_num
,
p_block
)
)
{
block_t
*
p_dts_block
=
block_FifoGet
(
p_sys
->
p_dts_fifo
);
p_block
->
i_dts
=
p_dts_block
->
i_dts
;
p_block
->
i_pts
=
GetPicturePTS
(
p_enc
,
u_pic_num
);
block_Release
(
p_dts_block
);
block_ChainAppend
(
&
p_output_chain
,
p_block
);
}
else
{
/* End of sequence */
block_ChainAppend
(
&
p_output_chain
,
p_block
);
}
break
;
}
default:
break
;
}
}
while
(
b_go
);
return
p_output_chain
;
}
/*****************************************************************************
* CloseEncoder: Schro encoder destruction
*****************************************************************************/
static
void
CloseEncoder
(
vlc_object_t
*
p_this
)
{
encoder_t
*
p_enc
=
(
encoder_t
*
)
p_this
;
encoder_sys_t
*
p_sys
=
p_enc
->
p_sys
;
/* Free the encoder resources */
if
(
p_sys
->
p_schro
)
schro_encoder_free
(
p_sys
->
p_schro
);
free
(
p_sys
->
p_format
);
if
(
p_sys
->
p_dts_fifo
)
block_FifoRelease
(
p_sys
->
p_dts_fifo
);
block_ChainRelease
(
p_sys
->
p_chain
);
free
(
p_sys
);
}
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