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
bc57d09c
Commit
bc57d09c
authored
May 12, 2002
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* All: simplifications.
parent
e3c06996
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
106 additions
and
219 deletions
+106
-219
plugins/ffmpeg/ffmpeg.c
plugins/ffmpeg/ffmpeg.c
+101
-213
plugins/ffmpeg/ffmpeg.h
plugins/ffmpeg/ffmpeg.h
+5
-6
No files found.
plugins/ffmpeg/ffmpeg.c
View file @
bc57d09c
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* ffmpeg.c: video decoder using ffmpeg library
* ffmpeg.c: video decoder using ffmpeg library
*****************************************************************************
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* Copyright (C) 1999-2001 VideoLAN
* $Id: ffmpeg.c,v 1.
7 2002/05/10 02:04:17
fenrir Exp $
* $Id: ffmpeg.c,v 1.
8 2002/05/12 06:51:08
fenrir Exp $
*
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
*
...
@@ -81,8 +81,8 @@ MODULE_CONFIG_START
...
@@ -81,8 +81,8 @@ MODULE_CONFIG_START
MODULE_CONFIG_STOP
MODULE_CONFIG_STOP
MODULE_INIT_START
MODULE_INIT_START
SET_DESCRIPTION
(
"ffmpeg video decoder
module (MSMPEG4
,MPEG4)"
)
SET_DESCRIPTION
(
"ffmpeg video decoder
(MSMPEG4v3
,MPEG4)"
)
ADD_CAPABILITY
(
DECODER
,
5
0
)
ADD_CAPABILITY
(
DECODER
,
7
0
)
ADD_SHORTCUT
(
"ffmpeg"
)
ADD_SHORTCUT
(
"ffmpeg"
)
MODULE_INIT_STOP
MODULE_INIT_STOP
...
@@ -119,8 +119,6 @@ static int decoder_Probe( u8 *pi_type )
...
@@ -119,8 +119,6 @@ static int decoder_Probe( u8 *pi_type )
{
{
switch
(
*
pi_type
)
switch
(
*
pi_type
)
{
{
/* case( MPEG1_VIDEO_ES ): marche pas pr le moment
case( MPEG2_VIDEO_ES ): */
case
(
MSMPEG4_VIDEO_ES
):
case
(
MSMPEG4_VIDEO_ES
):
case
(
MPEG4_VIDEO_ES
):
case
(
MPEG4_VIDEO_ES
):
return
(
0
);
return
(
0
);
...
@@ -197,99 +195,53 @@ static void __PES_NEXT( decoder_fifo_t *p_fifo )
...
@@ -197,99 +195,53 @@ static void __PES_NEXT( decoder_fifo_t *p_fifo )
vlc_mutex_unlock
(
&
p_fifo
->
data_lock
);
vlc_mutex_unlock
(
&
p_fifo
->
data_lock
);
}
}
static
void
__PACKET_REINIT
(
videodec_thread_t
*
p_vdec
)
static
__inline__
void
__GetFrame
(
videodec_thread_t
*
p_vdec
)
{
{
pes_packet_t
*
p_pes
;
pes_packet_t
*
p_pes
;
data_packet_t
*
p_data
;
byte_t
*
p_buffer
;
p_pes
=
__PES_GET
(
p_vdec
->
p_fifo
);
p_pes
=
__PES_GET
(
p_vdec
->
p_fifo
);
if
(
p_vdec
->
p_fifo
->
b_die
)
p_vdec
->
i_pts
=
p_pes
->
i_pts
;
{
return
;
}
p_vdec
->
p_data
=
p_pes
->
p_first
;
p_vdec
->
p_buff
=
p_vdec
->
p_data
->
p_payload_start
;
p_vdec
->
i_data_size
=
p_vdec
->
p_data
->
p_payload_end
-
p_vdec
->
p_data
->
p_payload_start
;
}
static
void
__PACKET_NEXT
(
videodec_thread_t
*
p_vdec
)
while
(
(
!
p_pes
->
i_nb_data
)
||
(
!
p_pes
->
i_pes_size
)
)
{
do
{
p_vdec
->
p_data
=
p_vdec
->
p_data
->
p_next
;
if
(
!
p_vdec
->
p_data
)
{
{
__PES_NEXT
(
p_vdec
->
p_fifo
);
__PES_NEXT
(
p_vdec
->
p_fifo
);
if
(
p_vdec
->
p_fifo
->
b_die
)
p_pes
=
__PES_GET
(
p_vdec
->
p_fifo
);
}
p_vdec
->
i_framesize
=
p_pes
->
i_pes_size
;
if
(
p_pes
->
i_nb_data
==
1
)
{
{
p_vdec
->
p_framedata
=
p_pes
->
p_first
->
p_payload_start
;
return
;
return
;
}
}
__PACKET_REINIT
(
p_vdec
);
/* get a buffer and gather all data packet */
}
p_vdec
->
p_framedata
=
p_buffer
=
malloc
(
p_pes
->
i_pes_size
);
else
p_data
=
p_pes
->
p_first
;
do
{
{
p_vdec
->
p_buff
=
p_vdec
->
p_data
->
p_payload_start
;
FAST_MEMCPY
(
p_buffer
,
p_vdec
->
i_data_size
=
p_vdec
->
p_data
->
p_payload_end
-
p_data
->
p_payload_start
,
p_vdec
->
p_data
->
p_payload_start
;
p_data
->
p_payload_end
-
p_data
->
p_payload_start
);
}
p_buffer
+=
p_data
->
p_payload_end
-
p_data
->
p_payload_start
;
p_data
=
p_data
->
p_next
;
}
while
(
(
p_vdec
->
i_data_size
<=
0
)
}
while
(
p_data
);
||
(
p_vdec
->
p_data
->
b_discard_payload
)
);
}
}
static
void
__PACKET_FILL
(
videodec_thread_t
*
p_vdec
)
static
__inline__
void
__NextFrame
(
videodec_thread_t
*
p_vdec
)
{
if
(
p_vdec
->
i_data_size
<=
0
)
{
__PACKET_NEXT
(
p_vdec
);
}
}
/* call only two times so inline for faster */
static
__inline__
void
__ConvertAVPictureToPicture
(
AVPicture
*
p_avpicture
,
picture_t
*
p_picture
)
{
{
int
i_plane
,
i_line
,
i_inc
;
pes_packet_t
*
p_pes
;
u8
*
p_dest
,
*
p_src
;
for
(
i_plane
=
0
;
i_plane
<
__MIN
(
p_picture
->
i_planes
,
3
);
i_plane
++
)
p_pes
=
__PES_GET
(
p_vdec
->
p_fifo
);
{
if
(
p_pes
->
i_nb_data
!=
1
)
p_dest
=
p_picture
->
p
[
i_plane
].
p_pixels
;
p_src
=
p_avpicture
->
data
[
i_plane
];
if
(
(
!
p_dest
)
||
(
!
p_src
))
{
return
;
}
i_inc
=
__MIN
(
p_picture
->
p
[
i_plane
].
i_pitch
,
p_avpicture
->
linesize
[
i_plane
]
);
for
(
i_line
=
0
;
i_line
<
p_picture
->
p
[
i_plane
].
i_lines
;
i_line
++
)
{
{
FAST_MEMCPY
(
p_dest
,
free
(
p_vdec
->
p_framedata
);
/* FIXME keep this buffer */
p_src
,
i_inc
);
p_dest
+=
p_picture
->
p
[
i_plane
].
i_pitch
;
p_src
+=
p_avpicture
->
linesize
[
i_plane
];
}
}
}
__PES_NEXT
(
p_vdec
->
p_fifo
);
}
}
static
__inline__
u32
__FfmpegChromaToFourCC
(
int
i_ffmpegchroma
)
{
switch
(
i_ffmpegchroma
)
{
case
(
PIX_FMT_YUV420P
):
case
(
PIX_FMT_YUV422
):
return
FOURCC_I420
;
case
(
PIX_FMT_RGB24
):
return
FOURCC_RV24
;
case
(
PIX_FMT_YUV422P
):
return
FOURCC_Y422
;
case
(
PIX_FMT_YUV444P
):
case
(
PIX_FMT_BGR24
):
default:
return
(
0
);
}
}
/*****************************************************************************
/*****************************************************************************
* decoder_Run: this function is called just after the thread is created
* decoder_Run: this function is called just after the thread is created
*****************************************************************************/
*****************************************************************************/
...
@@ -355,14 +307,11 @@ static int InitThread( videodec_thread_t *p_vdec )
...
@@ -355,14 +307,11 @@ static int InitThread( videodec_thread_t *p_vdec )
}
}
else
else
{
{
memset
(
&
p_vdec
->
format
,
0
,
sizeof
(
bitmapinfoheader_t
)
);
intf_ErrMsg
(
"vdec error: cannot get informations"
);
return
(
-
1
);
}
}
/* some codec need to have height and width initialized (msmepg4,mpeg4) */
/* we cannot create vout because we don't know what chroma */
/*init ffmpeg */
/*init ffmpeg */
/* TODO: add a global variable to know if init was already done
in case we use it also for audio */
if
(
!
b_ffmpeginit
)
if
(
!
b_ffmpeginit
)
{
{
avcodec_init
();
avcodec_init
();
...
@@ -377,11 +326,6 @@ static int InitThread( videodec_thread_t *p_vdec )
...
@@ -377,11 +326,6 @@ static int InitThread( videodec_thread_t *p_vdec )
switch
(
p_vdec
->
p_config
->
i_type
)
switch
(
p_vdec
->
p_config
->
i_type
)
{
{
case
(
MPEG1_VIDEO_ES
):
/* marche pas pr le moment */
case
(
MPEG2_VIDEO_ES
):
p_vdec
->
p_codec
=
avcodec_find_decoder
(
CODEC_ID_MPEG1VIDEO
);
p_vdec
->
psz_namecodec
=
"MPEG-1"
;
break
;
case
(
MSMPEG4_VIDEO_ES
):
case
(
MSMPEG4_VIDEO_ES
):
p_vdec
->
p_codec
=
avcodec_find_decoder
(
CODEC_ID_MSMPEG4
);
p_vdec
->
p_codec
=
avcodec_find_decoder
(
CODEC_ID_MSMPEG4
);
p_vdec
->
psz_namecodec
=
"MS MPEG-4/divx"
;
p_vdec
->
psz_namecodec
=
"MS MPEG-4/divx"
;
...
@@ -407,7 +351,7 @@ static int InitThread( videodec_thread_t *p_vdec )
...
@@ -407,7 +351,7 @@ static int InitThread( videodec_thread_t *p_vdec )
p_vdec
->
p_context
->
width
=
p_vdec
->
format
.
i_width
;
p_vdec
->
p_context
->
width
=
p_vdec
->
format
.
i_width
;
p_vdec
->
p_context
->
height
=
p_vdec
->
format
.
i_height
;
p_vdec
->
p_context
->
height
=
p_vdec
->
format
.
i_height
;
p_vdec
->
p_context
->
pix_fmt
=
PIX_FMT_YUV420P
;
p_vdec
->
p_context
->
pix_fmt
=
PIX_FMT_YUV420P
;
/* I420 */
if
(
avcodec_open
(
p_vdec
->
p_context
,
p_vdec
->
p_codec
)
<
0
)
if
(
avcodec_open
(
p_vdec
->
p_context
,
p_vdec
->
p_codec
)
<
0
)
{
{
...
@@ -420,7 +364,25 @@ static int InitThread( videodec_thread_t *p_vdec )
...
@@ -420,7 +364,25 @@ static int InitThread( videodec_thread_t *p_vdec )
intf_WarnMsg
(
1
,
"vdec info: ffmpeg codec (%s) started"
,
intf_WarnMsg
(
1
,
"vdec info: ffmpeg codec (%s) started"
,
p_vdec
->
psz_namecodec
);
p_vdec
->
psz_namecodec
);
}
}
/* destroy each p_vout */
/* create vout */
p_vdec
->
p_vout
=
vout_CreateThread
(
NULL
,
p_vdec
->
format
.
i_width
,
p_vdec
->
format
.
i_height
,
FOURCC_I420
,
VOUT_ASPECT_FACTOR
*
p_vdec
->
format
.
i_width
/
p_vdec
->
format
.
i_height
);
if
(
!
p_vdec
->
p_vout
)
{
intf_ErrMsg
(
"vdec error: can't open vout, aborting"
);
avcodec_close
(
p_vdec
->
p_context
);
intf_WarnMsg
(
1
,
"vdec info: ffmpeg codec (%s) stopped"
,
p_vdec
->
psz_namecodec
);
return
(
-
1
);
}
vlc_mutex_lock
(
&
p_vout_bank
->
lock
);
vlc_mutex_lock
(
&
p_vout_bank
->
lock
);
if
(
p_vout_bank
->
i_count
!=
0
)
if
(
p_vout_bank
->
i_count
!=
0
)
{
{
...
@@ -428,10 +390,11 @@ static int InitThread( videodec_thread_t *p_vdec )
...
@@ -428,10 +390,11 @@ static int InitThread( videodec_thread_t *p_vdec )
vout_DestroyThread
(
p_vout_bank
->
pp_vout
[
0
],
NULL
);
vout_DestroyThread
(
p_vout_bank
->
pp_vout
[
0
],
NULL
);
vlc_mutex_lock
(
&
p_vout_bank
->
lock
);
vlc_mutex_lock
(
&
p_vout_bank
->
lock
);
p_vout_bank
->
i_count
--
;
p_vout_bank
->
i_count
--
;
p_vout_bank
->
pp_vout
[
0
]
=
NULL
;
}
}
p_vout_bank
->
i_count
++
;
p_vout_bank
->
pp_vout
[
0
]
=
p_vdec
->
p_vout
;
vlc_mutex_unlock
(
&
p_vout_bank
->
lock
);
vlc_mutex_unlock
(
&
p_vout_bank
->
lock
);
__PACKET_REINIT
(
p_vdec
);
return
(
0
);
return
(
0
);
}
}
...
@@ -472,98 +435,38 @@ static void EndThread( videodec_thread_t *p_vdec )
...
@@ -472,98 +435,38 @@ static void EndThread( videodec_thread_t *p_vdec )
static
void
DecodeThread
(
videodec_thread_t
*
p_vdec
)
static
void
DecodeThread
(
videodec_thread_t
*
p_vdec
)
{
{
int
i_len
;
int
i_plane
;
int
i_status
;
int
b_gotpicture
;
int
b_gotpicture
;
int
b_convert
;
mtime_t
i_pts
;
AVPicture
avpicture
;
/* ffmpeg picture */
AVPicture
avpicture
;
/* ffmpeg picture */
u32
i_chroma
;
picture_t
*
p_pic
;
/* videolan picture */
picture_t
*
p_picture
;
/* videolan picture */
/* we have to get a frame stored in a pes
/* we have to get a frame stored in a pes
give it to ffmpeg decoder
give it to ffmpeg decoder
and send the image to the output */
and send the image to the output */
/* when we have the first image we create the video output */
i_pts
=
0
;
__GetFrame
(
p_vdec
);
do
{
__PACKET_FILL
(
p_vdec
);
if
(
(
p_vdec
->
p_fifo
->
b_die
)
||
(
p_vdec
->
p_fifo
->
b_error
)
)
{
return
;
}
/* save pts */
if
(
!
i_pts
)
{
i_pts
=
__PES_GET
(
p_vdec
->
p_fifo
)
->
i_pts
;}
i_len
=
avcodec_decode_video
(
p_vdec
->
p_context
,
i_status
=
avcodec_decode_video
(
p_vdec
->
p_context
,
&
avpicture
,
&
avpicture
,
&
b_gotpicture
,
&
b_gotpicture
,
p_vdec
->
p_buff
,
p_vdec
->
p_framedata
,
p_vdec
->
i_data_size
);
p_vdec
->
i_framesize
);
__NextFrame
(
p_vdec
);
if
(
i_len
<
0
)
if
(
i_status
<
0
)
{
{
intf_WarnMsg
(
3
,
"vdec error: cannot decode one frame (%d bytes)"
,
intf_WarnMsg
(
2
,
"vdec error: cannot decode one frame (%d bytes)"
,
p_vdec
->
i_data_size
);
p_vdec
->
i_framesize
);
__PES_NEXT
(
p_vdec
->
p_fifo
);
__PACKET_REINIT
(
p_vdec
);
return
;
return
;
}
}
p_vdec
->
i_data_size
-=
i_len
;
if
(
!
b_gotpicture
)
p_vdec
->
p_buff
+=
i_len
;
}
while
(
!
b_gotpicture
);
if
(
!
(
i_chroma
=
__FfmpegChromaToFourCC
(
p_vdec
->
p_context
->
pix_fmt
)
)
)
{
{
b_convert
=
1
;
return
;
i_chroma
=
FOURCC_I420
;
}
else
{
b_convert
=
0
;
}
}
/* Send decoded frame to vout */
/* Send decoded frame to vout */
if
(
!
p_vdec
->
p_vout
)
{
/* create vout */
/* ffmpeg set it for us with some codec */
while
(
!
(
p_pic
=
vout_CreatePicture
(
p_vdec
->
p_vout
,
0
,
0
,
0
)
)
)
if
(
(
!
p_vdec
->
format
.
i_width
)
||
(
!
p_vdec
->
format
.
i_height
)
)
{
p_vdec
->
format
.
i_width
=
p_vdec
->
p_context
->
width
;
p_vdec
->
format
.
i_height
=
p_vdec
->
p_context
->
height
;
}
/* calculate i_aspect */
p_vdec
->
i_aspect
=
VOUT_ASPECT_FACTOR
*
p_vdec
->
format
.
i_width
/
p_vdec
->
format
.
i_height
;
p_vdec
->
i_chroma
=
i_chroma
;
p_vdec
->
p_vout
=
vout_CreateThread
(
NULL
,
p_vdec
->
format
.
i_width
,
p_vdec
->
format
.
i_height
,
p_vdec
->
i_chroma
,
p_vdec
->
i_aspect
);
if
(
!
p_vdec
->
p_vout
)
{
intf_ErrMsg
(
"vdec error: can't open vout, aborting"
);
p_vdec
->
p_fifo
->
b_error
=
1
;
return
;
}
vlc_mutex_lock
(
&
p_vout_bank
->
lock
);
p_vout_bank
->
pp_vout
[
0
]
=
p_vdec
->
p_vout
;
p_vout_bank
->
i_count
++
;
vlc_mutex_unlock
(
&
p_vout_bank
->
lock
);
}
while
(
(
p_picture
=
vout_CreatePicture
(
p_vdec
->
p_vout
,
0
,
/* ??? */
0
,
/* ??? */
0
)
)
/* ??? */
==
NULL
)
{
{
if
(
p_vdec
->
p_fifo
->
b_die
||
p_vdec
->
p_fifo
->
b_error
)
if
(
p_vdec
->
p_fifo
->
b_die
||
p_vdec
->
p_fifo
->
b_error
)
{
{
...
@@ -572,43 +475,28 @@ static void DecodeThread( videodec_thread_t *p_vdec )
...
@@ -572,43 +475,28 @@ static void DecodeThread( videodec_thread_t *p_vdec )
msleep
(
VOUT_OUTMEM_SLEEP
);
msleep
(
VOUT_OUTMEM_SLEEP
);
}
}
if
(
b_convert
)
for
(
i_plane
=
0
;
i_plane
<
p_pic
->
i_planes
;
i_plane
++
)
{
{
/* we convert in a supported format */
int
i_size
;
int
i_status
;
int
i_line
;
u8
*
p_buff
;
byte_t
*
p_dest
=
p_pic
->
p
[
i_plane
].
p_pixels
;
AVPicture
avpicture_tmp
;
byte_t
*
p_src
=
avpicture
.
data
[
i_plane
];
if
(
(
!
p_dest
)
||
(
!
p_src
))
p_buff
=
malloc
(
avpicture_get_size
(
PIX_FMT_YUV420P
,
p_vdec
->
p_context
->
width
,
p_vdec
->
p_context
->
height
)
);
avpicture_fill
(
&
avpicture_tmp
,
p_buff
,
PIX_FMT_YUV420P
,
p_vdec
->
p_context
->
width
,
p_vdec
->
p_context
->
height
);
i_status
=
img_convert
(
&
avpicture_tmp
,
PIX_FMT_YUV420P
,
&
avpicture
,
p_vdec
->
p_context
->
pix_fmt
,
p_vdec
->
p_context
->
width
,
p_vdec
->
p_context
->
height
);
if
(
i_status
<
0
)
{
{
intf_ErrMsg
(
"vdec error: cannot convert picture in known chroma"
);
break
;
return
;
}
__ConvertAVPictureToPicture
(
&
avpicture_tmp
,
p_picture
);
free
(
p_buff
);
/* FIXME try to alloc only one time */
}
}
else
i_size
=
__MIN
(
p_pic
->
p
[
i_plane
].
i_pitch
,
avpicture
.
linesize
[
i_plane
]
);
for
(
i_line
=
0
;
i_line
<
p_pic
->
p
[
i_plane
].
i_lines
;
i_line
++
)
{
{
__ConvertAVPictureToPicture
(
&
avpicture
,
p_picture
);
FAST_MEMCPY
(
p_dest
,
p_src
,
i_size
);
p_dest
+=
p_pic
->
p
[
i_plane
].
i_pitch
;
p_src
+=
avpicture
.
linesize
[
i_plane
];
}
}
}
vout_DatePicture
(
p_vdec
->
p_vout
,
p_pic
ture
,
i_pts
);
vout_DatePicture
(
p_vdec
->
p_vout
,
p_pic
,
p_vdec
->
i_pts
);
vout_DisplayPicture
(
p_vdec
->
p_vout
,
p_pic
ture
);
vout_DisplayPicture
(
p_vdec
->
p_vout
,
p_pic
);
return
;
return
;
}
}
...
...
plugins/ffmpeg/ffmpeg.h
View file @
bc57d09c
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* ffmpeg_vdec.h: video decoder using ffmpeg library
* ffmpeg_vdec.h: video decoder using ffmpeg library
*****************************************************************************
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* Copyright (C) 2001 VideoLAN
* $Id: ffmpeg.h,v 1.
1 2002/04/23 23:44:36
fenrir Exp $
* $Id: ffmpeg.h,v 1.
2 2002/05/12 06:51:08
fenrir Exp $
*
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
*
...
@@ -47,11 +47,10 @@ typedef struct videodec_thread_s
...
@@ -47,11 +47,10 @@ typedef struct videodec_thread_s
AVCodecContext
context
,
*
p_context
;
AVCodecContext
context
,
*
p_context
;
AVCodec
*
p_codec
;
AVCodec
*
p_codec
;
vout_thread_t
*
p_vout
;
vout_thread_t
*
p_vout
;
int
i_aspect
;
u32
i_chroma
;
char
*
psz_namecodec
;
char
*
psz_namecodec
;
/* private */
/* private */
data_packet_t
*
p_data
;
mtime_t
i_pts
;
byte_t
*
p_buff
;
int
i_framesize
;
int
i_data_size
;
byte_t
*
p_framedata
;
}
videodec_thread_t
;
}
videodec_thread_t
;
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