Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Steve Lhomme
VLC
Commits
7e676a02
Commit
7e676a02
authored
Nov 11, 2008
by
Laurent Aimar
Browse files
Added initial skeleton for es_out timeshift support.
It is not yet functionnal.
parent
cdf95dd2
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/Makefile.am
View file @
7e676a02
...
...
@@ -309,6 +309,7 @@ SOURCES_libvlc_common = \
input/decoder_synchro.c
\
input/demux.c
\
input/es_out.c
\
input/es_out_timeshift.c
\
input/input.c
\
input/meta.c
\
input/access.h
\
...
...
@@ -316,6 +317,7 @@ SOURCES_libvlc_common = \
input/decoder.h
\
input/demux.h
\
input/es_out.h
\
input/es_out_timeshift.h
\
input/stream.h
\
input/input_internal.h
\
input/vlm_internal.h
\
...
...
src/input/es_out.c
View file @
7e676a02
...
...
@@ -2210,7 +2210,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
return
VLC_EGENERIC
;
}
case
ES_OUT_SET_FMT
:
case
ES_OUT_SET_
ES_
FMT
:
{
/* This ain't pretty but is need by some demuxers (eg. Ogg )
* to update the p_extra data */
...
...
src/input/es_out_timeshift.c
0 → 100644
View file @
7e676a02
/*****************************************************************************
* es_out_timeshift.c: Es Out timeshift.
*****************************************************************************
* Copyright (C) 2008 Laurent Aimar
* $Id$
*
* Authors: Laurent Aimar < fenrir _AT_ via _DOT_ ecp _DOT_ fr>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#if defined (WIN32) && !defined (UNDER_CE)
# include <direct.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#include <vlc_common.h>
#include <vlc_charset.h>
#include <vlc_input.h>
#include <vlc_es_out.h>
#include <vlc_block.h>
#include "input_internal.h"
#include "es_out.h"
#include "es_out_timeshift.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
enum
{
C_ADD
,
C_SEND
,
C_DEL
,
C_CONTROL
,
};
typedef
struct
{
int
i_type
;
union
{
struct
{
es_out_id_t
*
p_es
;
es_format_t
*
p_fmt
;
}
add
;
struct
{
es_out_id_t
*
p_es
;
}
del
;
struct
{
es_out_id_t
*
p_es
;
block_t
*
p_block
;
}
send
;
struct
{
int
i_query
;
bool
b_bool
;
bool
*
pb_bool
;
int
i_int
;
int
*
pi_int
;
int64_t
i_i64
;
vlc_meta_t
*
p_meta
;
vlc_epg_t
*
p_epg
;
es_out_id_t
*
p_es
;
es_format_t
*
p_fmt
;
}
control
;
};
}
ts_cmd_t
;
struct
es_out_id_t
{
es_out_id_t
*
p_es
;
};
struct
es_out_sys_t
{
input_thread_t
*
p_input
;
es_out_t
*
p_out
;
/* Configuration */
int64_t
i_tmp_size_max
;
/* Maximal temporary file size in byte */
char
*
psz_tmp_path
;
/* Path for temporary files */
/* Lock for all following fields */
vlc_mutex_t
lock
;
/* */
bool
b_delayed
;
/* */
int
i_es
;
es_out_id_t
**
pp_es
;
/* */
int
i_cmd
;
ts_cmd_t
**
pp_cmd
;
};
static
es_out_id_t
*
Add
(
es_out_t
*
,
const
es_format_t
*
);
static
int
Send
(
es_out_t
*
,
es_out_id_t
*
,
block_t
*
);
static
void
Del
(
es_out_t
*
,
es_out_id_t
*
);
static
int
Control
(
es_out_t
*
,
int
i_query
,
va_list
);
static
void
Destroy
(
es_out_t
*
);
static
void
CmdPush
(
es_out_t
*
,
const
ts_cmd_t
*
);
static
int
CmdPop
(
es_out_t
*
p_out
,
ts_cmd_t
*
p_cmd
);
static
int
CmdInitAdd
(
ts_cmd_t
*
,
es_out_id_t
*
,
const
es_format_t
*
,
bool
b_copy
);
static
void
CmdInitSend
(
ts_cmd_t
*
,
es_out_id_t
*
,
block_t
*
);
static
int
CmdInitDel
(
ts_cmd_t
*
,
es_out_id_t
*
);
static
int
CmdInitControl
(
ts_cmd_t
*
,
int
i_query
,
va_list
,
bool
b_copy
);
static
void
CmdExecuteAdd
(
es_out_t
*
,
ts_cmd_t
*
);
static
int
CmdExecuteSend
(
es_out_t
*
,
ts_cmd_t
*
);
static
void
CmdExecuteDel
(
es_out_t
*
,
ts_cmd_t
*
);
static
int
CmdExecuteControl
(
es_out_t
*
,
ts_cmd_t
*
);
static
void
CmdCleanAdd
(
ts_cmd_t
*
);
static
void
CmdCleanSend
(
ts_cmd_t
*
);
static
void
CmdCleanControl
(
ts_cmd_t
*
p_cmd
);
static
char
*
GetTmpPath
(
char
*
psz_path
);
static
FILE
*
GetTmpFile
(
const
char
*
psz_path
);
/*****************************************************************************
* input_EsOutTimeshiftNew:
*****************************************************************************/
es_out_t
*
input_EsOutTimeshiftNew
(
input_thread_t
*
p_input
,
es_out_t
*
p_next_out
)
{
es_out_t
*
p_out
=
malloc
(
sizeof
(
*
p_out
)
);
if
(
!
p_out
)
return
NULL
;
es_out_sys_t
*
p_sys
=
malloc
(
sizeof
(
*
p_sys
)
);
if
(
!
p_sys
)
{
free
(
p_out
);
return
NULL
;
}
/* */
p_out
->
pf_add
=
Add
;
p_out
->
pf_send
=
Send
;
p_out
->
pf_del
=
Del
;
p_out
->
pf_control
=
Control
;
p_out
->
pf_destroy
=
Destroy
;
p_out
->
p_sys
=
p_sys
;
p_out
->
b_sout
=
p_input
->
p
->
p_sout
!=
NULL
;
/* */
p_sys
->
p_input
=
p_input
;
p_sys
->
p_out
=
p_next_out
;
vlc_mutex_init_recursive
(
&
p_sys
->
lock
);
p_sys
->
b_delayed
=
false
;
TAB_INIT
(
p_sys
->
i_es
,
p_sys
->
pp_es
);
TAB_INIT
(
p_sys
->
i_cmd
,
p_sys
->
pp_cmd
);
/* TODO config
* timeshift-granularity
* timeshift-path
*/
p_sys
->
i_tmp_size_max
=
50
*
1024
*
1024
;
p_sys
->
psz_tmp_path
=
GetTmpPath
(
NULL
);
return
p_out
;
}
/*****************************************************************************
* Internal functions
*****************************************************************************/
static
void
Destroy
(
es_out_t
*
p_out
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
while
(
p_sys
->
i_cmd
>
0
)
{
ts_cmd_t
cmd
;
if
(
CmdPop
(
p_out
,
&
cmd
)
)
break
;
switch
(
cmd
.
i_type
)
{
case
C_ADD
:
CmdCleanAdd
(
&
cmd
);
break
;
case
C_SEND
:
CmdCleanSend
(
&
cmd
);
break
;
case
C_CONTROL
:
CmdCleanControl
(
&
cmd
);
break
;
case
C_DEL
:
break
;
default:
assert
(
0
);
break
;
}
}
TAB_CLEAN
(
p_sys
->
i_cmd
,
p_sys
->
pp_cmd
);
while
(
p_sys
->
i_es
>
0
)
Del
(
p_out
,
p_sys
->
pp_es
[
0
]
);
TAB_CLEAN
(
p_sys
->
i_es
,
p_sys
->
pp_es
);
free
(
p_sys
->
psz_tmp_path
);
vlc_mutex_destroy
(
&
p_sys
->
lock
);
free
(
p_sys
);
free
(
p_out
);
}
static
es_out_id_t
*
Add
(
es_out_t
*
p_out
,
const
es_format_t
*
p_fmt
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
ts_cmd_t
cmd
;
es_out_id_t
*
p_es
=
malloc
(
sizeof
(
*
p_es
)
);
if
(
!
p_es
)
return
NULL
;
vlc_mutex_lock
(
&
p_sys
->
lock
);
if
(
CmdInitAdd
(
&
cmd
,
p_es
,
p_fmt
,
p_sys
->
b_delayed
)
)
{
vlc_mutex_unlock
(
&
p_sys
->
lock
);
free
(
p_es
);
return
NULL
;
}
TAB_APPEND
(
p_sys
->
i_es
,
p_sys
->
pp_es
,
p_es
);
if
(
p_sys
->
b_delayed
)
CmdPush
(
p_out
,
&
cmd
);
else
CmdExecuteAdd
(
p_out
,
&
cmd
);
vlc_mutex_unlock
(
&
p_sys
->
lock
);
return
p_es
;
}
static
int
Send
(
es_out_t
*
p_out
,
es_out_id_t
*
p_es
,
block_t
*
p_block
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
ts_cmd_t
cmd
;
int
i_ret
=
VLC_SUCCESS
;
vlc_mutex_lock
(
&
p_sys
->
lock
);
CmdInitSend
(
&
cmd
,
p_es
,
p_block
);
if
(
p_sys
->
b_delayed
)
CmdPush
(
p_out
,
&
cmd
);
else
i_ret
=
CmdExecuteSend
(
p_out
,
&
cmd
)
;
vlc_mutex_unlock
(
&
p_sys
->
lock
);
return
i_ret
;
}
static
void
Del
(
es_out_t
*
p_out
,
es_out_id_t
*
p_es
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
ts_cmd_t
cmd
;
vlc_mutex_lock
(
&
p_sys
->
lock
);
CmdInitDel
(
&
cmd
,
p_es
);
if
(
p_sys
->
b_delayed
)
CmdPush
(
p_out
,
&
cmd
);
else
CmdExecuteDel
(
p_out
,
&
cmd
);
TAB_REMOVE
(
p_sys
->
i_es
,
p_sys
->
pp_es
,
p_es
);
vlc_mutex_unlock
(
&
p_sys
->
lock
);
}
static
int
ControlLocked
(
es_out_t
*
p_out
,
int
i_query
,
va_list
args
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
switch
(
i_query
)
{
/* Invalid query for this es_out level */
case
ES_OUT_SET_ES_BY_ID
:
case
ES_OUT_RESTART_ES_BY_ID
:
case
ES_OUT_SET_ES_DEFAULT_BY_ID
:
case
ES_OUT_SET_DELAY
:
case
ES_OUT_SET_RECORD_STATE
:
assert
(
0
);
return
VLC_EGENERIC
;
/* TODO ? or to remove ? */
case
ES_OUT_GET_TS
:
return
VLC_EGENERIC
;
/* Pass-through control */
case
ES_OUT_SET_ACTIVE
:
case
ES_OUT_GET_ACTIVE
:
case
ES_OUT_SET_MODE
:
case
ES_OUT_GET_MODE
:
case
ES_OUT_SET_GROUP
:
case
ES_OUT_GET_GROUP
:
case
ES_OUT_SET_PCR
:
case
ES_OUT_SET_GROUP_PCR
:
case
ES_OUT_RESET_PCR
:
case
ES_OUT_SET_NEXT_DISPLAY_TIME
:
case
ES_OUT_SET_GROUP_META
:
case
ES_OUT_SET_GROUP_EPG
:
case
ES_OUT_DEL_GROUP
:
case
ES_OUT_SET_ES
:
case
ES_OUT_RESTART_ES
:
case
ES_OUT_SET_ES_DEFAULT
:
case
ES_OUT_SET_ES_STATE
:
case
ES_OUT_GET_ES_STATE
:
case
ES_OUT_SET_ES_FMT
:
{
ts_cmd_t
cmd
;
if
(
CmdInitControl
(
&
cmd
,
i_query
,
args
,
p_sys
->
b_delayed
)
)
return
VLC_EGENERIC
;
if
(
p_sys
->
b_delayed
)
{
CmdPush
(
p_out
,
&
cmd
);
return
VLC_SUCCESS
;
}
return
CmdExecuteControl
(
p_out
,
&
cmd
);
}
/* Special control */
case
ES_OUT_GET_WAKE_UP
:
/* TODO ? */
case
ES_OUT_GET_BUFFERING
:
case
ES_OUT_GET_EMPTY
:
case
ES_OUT_SET_PAUSE_STATE
:
case
ES_OUT_SET_RATE
:
case
ES_OUT_SET_TIME
:
case
ES_OUT_SET_FRAME_NEXT
:
if
(
p_sys
->
b_delayed
)
{
/* TODO */
}
return
es_out_vaControl
(
p_sys
->
p_out
,
i_query
,
args
);
default:
msg_Err
(
p_sys
->
p_input
,
"Unknown es_out_Control query !"
);
assert
(
0
);
return
VLC_EGENERIC
;
}
}
static
int
Control
(
es_out_t
*
p_out
,
int
i_query
,
va_list
args
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
int
i_ret
;
vlc_mutex_lock
(
&
p_sys
->
lock
);
i_ret
=
ControlLocked
(
p_out
,
i_query
,
args
);
vlc_mutex_unlock
(
&
p_sys
->
lock
);
return
i_ret
;
}
/*****************************************************************************
*
*****************************************************************************/
static
void
CmdPush
(
es_out_t
*
p_out
,
const
ts_cmd_t
*
p_cmd
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
ts_cmd_t
*
p_dup
=
malloc
(
sizeof
(
*
p_dup
)
);
if
(
p_dup
)
{
*
p_dup
=
*
p_cmd
;
TAB_APPEND
(
p_sys
->
i_cmd
,
p_sys
->
pp_cmd
,
p_dup
);
}
}
static
int
CmdPop
(
es_out_t
*
p_out
,
ts_cmd_t
*
p_cmd
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
if
(
p_sys
->
i_cmd
<=
0
)
return
VLC_EGENERIC
;
*
p_cmd
=
*
p_sys
->
pp_cmd
[
0
];
free
(
p_sys
->
pp_cmd
[
0
]
);
TAB_REMOVE
(
p_sys
->
i_cmd
,
p_sys
->
pp_cmd
,
p_sys
->
pp_cmd
[
0
]
);
return
VLC_SUCCESS
;
}
static
int
CmdInitAdd
(
ts_cmd_t
*
p_cmd
,
es_out_id_t
*
p_es
,
const
es_format_t
*
p_fmt
,
bool
b_copy
)
{
p_cmd
->
i_type
=
C_ADD
;
p_cmd
->
add
.
p_es
=
p_es
;
if
(
b_copy
)
{
p_cmd
->
add
.
p_fmt
=
malloc
(
sizeof
(
*
p_fmt
)
);
if
(
!
p_cmd
->
add
.
p_fmt
)
return
VLC_EGENERIC
;
es_format_Copy
(
p_cmd
->
add
.
p_fmt
,
p_fmt
);
}
else
{
p_cmd
->
add
.
p_fmt
=
(
es_format_t
*
)
p_fmt
;
}
return
VLC_SUCCESS
;
}
static
void
CmdExecuteAdd
(
es_out_t
*
p_out
,
ts_cmd_t
*
p_cmd
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
p_cmd
->
add
.
p_es
->
p_es
=
es_out_Add
(
p_sys
->
p_out
,
p_cmd
->
add
.
p_fmt
);
}
static
void
CmdCleanAdd
(
ts_cmd_t
*
p_cmd
)
{
es_format_Clean
(
p_cmd
->
add
.
p_fmt
);
free
(
p_cmd
->
add
.
p_fmt
);
}
static
void
CmdInitSend
(
ts_cmd_t
*
p_cmd
,
es_out_id_t
*
p_es
,
block_t
*
p_block
)
{
p_cmd
->
i_type
=
C_SEND
;
p_cmd
->
send
.
p_es
=
p_es
;
p_cmd
->
send
.
p_block
=
p_block
;
}
static
int
CmdExecuteSend
(
es_out_t
*
p_out
,
ts_cmd_t
*
p_cmd
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
block_t
*
p_block
=
p_cmd
->
send
.
p_block
;
p_cmd
->
send
.
p_block
=
NULL
;
if
(
p_block
)
{
if
(
p_cmd
->
send
.
p_es
->
p_es
)
return
es_out_Send
(
p_sys
->
p_out
,
p_cmd
->
send
.
p_es
->
p_es
,
p_block
);
block_Release
(
p_block
);
}
return
VLC_EGENERIC
;
}
static
void
CmdCleanSend
(
ts_cmd_t
*
p_cmd
)
{
if
(
p_cmd
->
send
.
p_block
)
block_Release
(
p_cmd
->
send
.
p_block
);
}
static
int
CmdInitDel
(
ts_cmd_t
*
p_cmd
,
es_out_id_t
*
p_es
)
{
p_cmd
->
i_type
=
C_DEL
;
p_cmd
->
del
.
p_es
=
p_es
;
return
VLC_SUCCESS
;
}
static
void
CmdExecuteDel
(
es_out_t
*
p_out
,
ts_cmd_t
*
p_cmd
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
if
(
p_cmd
->
del
.
p_es
->
p_es
)
es_out_Del
(
p_sys
->
p_out
,
p_cmd
->
del
.
p_es
->
p_es
);
free
(
p_cmd
->
del
.
p_es
);
}
static
int
CmdInitControl
(
ts_cmd_t
*
p_cmd
,
int
i_query
,
va_list
args
,
bool
b_copy
)
{
p_cmd
->
i_type
=
C_CONTROL
;
p_cmd
->
control
.
i_query
=
i_query
;
switch
(
i_query
)
{
/* Pass-through control */
case
ES_OUT_SET_ACTIVE
:
/* arg1= bool */
p_cmd
->
control
.
b_bool
=
(
bool
)
va_arg
(
args
,
int
);
break
;
case
ES_OUT_GET_ACTIVE
:
/* arg1= bool* */
p_cmd
->
control
.
pb_bool
=
(
bool
*
)
va_arg
(
args
,
bool
*
);
break
;
case
ES_OUT_SET_MODE
:
/* arg1= int */
case
ES_OUT_SET_GROUP
:
/* arg1= int */
case
ES_OUT_DEL_GROUP
:
/* arg1=int i_group */
p_cmd
->
control
.
i_int
=
(
int
)
va_arg
(
args
,
int
);
break
;
case
ES_OUT_GET_MODE
:
/* arg2= int* */
case
ES_OUT_GET_GROUP
:
/* arg1= int* */
p_cmd
->
control
.
pi_int
=
(
int
*
)
va_arg
(
args
,
int
*
);
break
;
case
ES_OUT_SET_PCR
:
/* arg1=int64_t i_pcr(microsecond!) (using default group 0)*/
case
ES_OUT_SET_NEXT_DISPLAY_TIME
:
/* arg1=int64_t i_pts(microsecond) */
p_cmd
->
control
.
i_i64
=
(
int64_t
)
va_arg
(
args
,
int64_t
);
break
;
case
ES_OUT_SET_GROUP_PCR
:
/* arg1= int i_group, arg2=int64_t i_pcr(microsecond!)*/
p_cmd
->
control
.
i_int
=
(
int
)
va_arg
(
args
,
int
);
p_cmd
->
control
.
i_i64
=
(
int64_t
)
va_arg
(
args
,
int64_t
);
break
;
case
ES_OUT_RESET_PCR
:
/* no arg */
break
;
case
ES_OUT_SET_GROUP_META
:
/* arg1=int i_group arg2=vlc_meta_t* */
{
p_cmd
->
control
.
i_int
=
(
int
)
va_arg
(
args
,
int
);
vlc_meta_t
*
p_meta
=
(
vlc_meta_t
*
)
va_arg
(
args
,
vlc_meta_t
*
);
if
(
b_copy
)
{
p_cmd
->
control
.
p_meta
=
vlc_meta_New
();
if
(
!
p_cmd
->
control
.
p_meta
)
return
VLC_EGENERIC
;
vlc_meta_Merge
(
p_cmd
->
control
.
p_meta
,
p_meta
);
}
else
{
p_cmd
->
control
.
p_meta
=
p_meta
;
}
break
;
}
case
ES_OUT_SET_GROUP_EPG
:
/* arg1=int i_group arg2=vlc_epg_t* */
{
p_cmd
->
control
.
i_int
=
(
int
)
va_arg
(
args
,
int
);
vlc_epg_t
*
p_epg
=
(
vlc_epg_t
*
)
va_arg
(
args
,
vlc_epg_t
*
);
if
(
b_copy
)
{
p_cmd
->
control
.
p_epg
=
vlc_epg_New
(
p_epg
->
psz_name
);
if
(
!
p_cmd
->
control
.
p_epg
)
return
VLC_EGENERIC
;
for
(
int
i
=
0
;
i
<
p_epg
->
i_event
;
i
++
)
{
vlc_epg_event_t
*
p_evt
=
p_epg
->
pp_event
[
i
];
vlc_epg_AddEvent
(
p_cmd
->
control
.
p_epg
,
p_evt
->
i_start
,
p_evt
->
i_duration
,
p_evt
->
psz_name
,
p_evt
->
psz_short_description
,
p_evt
->
psz_description
);
}
vlc_epg_SetCurrent
(
p_cmd
->
control
.
p_epg
,
p_epg
->
p_current
?
p_epg
->
p_current
->
i_start
:
-
1
);
}
else
{
p_cmd
->
control
.
p_epg
=
p_epg
;
}
break
;
}
/* Modified control */
case
ES_OUT_SET_ES
:
/* arg1= es_out_id_t* */
case
ES_OUT_RESTART_ES
:
/* arg1= es_out_id_t* */
case
ES_OUT_SET_ES_DEFAULT
:
/* arg1= es_out_id_t* */
p_cmd
->
control
.
p_es
=
(
es_out_id_t
*
)
va_arg
(
args
,
es_out_id_t
*
);
break
;
case
ES_OUT_SET_ES_STATE
:
/* arg1= es_out_id_t* arg2=bool */
p_cmd
->
control
.
p_es
=
(
es_out_id_t
*
)
va_arg
(
args
,
es_out_id_t
*
);
p_cmd
->
control
.
b_bool
=
(
bool
)
va_arg
(
args
,
int
);
break
;
case
ES_OUT_GET_ES_STATE
:
/* arg1= es_out_id_t* arg2=bool* */
p_cmd
->
control
.
p_es
=
(
es_out_id_t
*
)
va_arg
(
args
,
es_out_id_t
*
);
p_cmd
->
control
.
pb_bool
=
(
bool
*
)
va_arg
(
args
,
bool
*
);
break
;
case
ES_OUT_SET_ES_FMT
:
/* arg1= es_out_id_t* arg2=es_format_t* */