Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
BC
public
mediastreamer2
Commits
ba56966d
Commit
ba56966d
authored
Aug 17, 2015
by
Simon Morlat
Browse files
recording video only works, but crashes in append mode
parent
84672db3
Changes
4
Hide whitespace changes
Inline
Side-by-side
include/mediastreamer2/mediastream.h
View file @
ba56966d
...
...
@@ -1109,11 +1109,9 @@ MS2_PUBLIC void video_stream_close_remote_play(VideoStream *stream);
* Open a recorder to record the video coming from remote end into a mkv file.
* This must be done before the stream is started.
**/
MS2_PUBLIC
int
video_stream_remote_record
_open
(
VideoStream
*
stream
,
const
char
*
filename
);
MS2_PUBLIC
MSFilter
*
video_stream_
open_
remote_record
(
VideoStream
*
stream
,
const
char
*
filename
);
MS2_PUBLIC
int
video_stream_remote_record_start
(
VideoStream
*
stream
);
MS2_PUBLIC
int
video_stream_remote_record_stop
(
VideoStream
*
stream
);
MS2_PUBLIC
void
video_stream_close_remote_record
(
VideoStream
*
stream
);
/**
* Small API to display a local preview window.
...
...
include/mediastreamer2/msinterfaces.h
View file @
ba56966d
...
...
@@ -203,7 +203,7 @@ typedef enum _MSRecorderState MSRecorderState;
/**
Interface
definitions for video decoders */
/**
Event
definitions for video decoders */
#define MS_VIDEO_DECODER_DECODING_ERRORS \
MS_FILTER_EVENT_NO_ARG(MSFilterVideoDecoderInterface,0)
#define MS_VIDEO_DECODER_FIRST_IMAGE_DECODED \
...
...
@@ -214,6 +214,8 @@ typedef enum _MSRecorderState MSRecorderState;
MS_FILTER_EVENT(MSFilterVideoDecoderInterface, 3, MSVideoCodecSLI)
#define MS_VIDEO_DECODER_SEND_RPSI \
MS_FILTER_EVENT(MSFilterVideoDecoderInterface, 4, MSVideoCodecRPSI)
/** Method definitions for video decoders */
#define MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION \
MS_FILTER_METHOD_NO_ARG(MSFilterVideoDecoderInterface, 5)
#define MS_VIDEO_DECODER_ENABLE_AVPF \
...
...
@@ -224,6 +226,8 @@ typedef enum _MSRecorderState MSRecorderState;
MS_FILTER_METHOD(MSFilterVideoDecoderInterface, 8, bool_t)
#define MS_VIDEO_DECODER_RECOVERED_FROM_ERRORS \
MS_FILTER_EVENT_NO_ARG(MSFilterVideoDecoderInterface, 9)
/** Interface definitions for video capture */
#define MS_VIDEO_CAPTURE_SET_DEVICE_ORIENTATION \
...
...
src/videofilters/mkv.c
View file @
ba56966d
...
...
@@ -34,6 +34,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define bool_t ambigous use ms_bool_t or matroska_bool_t
static
int
recorder_close
(
MSFilter
*
f
,
void
*
arg
);
/*********************************************************************************************
* Module interface *
*********************************************************************************************/
...
...
@@ -1576,10 +1578,12 @@ typedef struct {
MSRecorderState
state
;
Muxer
muxer
;
TimeCorrector
timeCorrector
;
ms_bool_t
needKeyFra
me
;
uint64_t
lastFirTi
me
;
const
MSFmtDescriptor
**
inputDescsList
;
Module
**
modulesList
;
TimeLoopCanceler
**
timeLoopCancelers
;
TimeLoopCanceler
**
timeLoopCancelers
;
ms_bool_t
needKeyFrame
;
ms_bool_t
tracksInitialized
;
}
MKVRecorder
;
static
void
recorder_init
(
MSFilter
*
f
)
{
...
...
@@ -1596,7 +1600,7 @@ static void recorder_init(MSFilter *f) {
obj
->
inputDescsList
=
(
const
MSFmtDescriptor
**
)
ms_new0
(
const
MSFmtDescriptor
*
,
f
->
desc
->
ninputs
);
obj
->
modulesList
=
(
Module
**
)
ms_new0
(
Module
*
,
f
->
desc
->
ninputs
);
obj
->
timeLoopCancelers
=
(
TimeLoopCanceler
**
)
ms_new0
(
TimeLoopCanceler
*
,
f
->
desc
->
ninputs
);
obj
->
lastFirTime
=
(
uint64_t
)
-
1
;
time_corrector_init
(
&
obj
->
timeCorrector
,
f
->
desc
->
ninputs
);
f
->
data
=
obj
;
...
...
@@ -1606,10 +1610,10 @@ static void recorder_uninit(MSFilter *f){
MKVRecorder
*
obj
=
(
MKVRecorder
*
)
f
->
data
;
int
i
;
muxer_uninit
(
&
obj
->
muxer
);
if
(
obj
->
state
!=
MSRecorderClosed
)
{
matroska_close_file
(
&
obj
->
file
);
recorder_close
(
f
,
NULL
);
}
muxer_uninit
(
&
obj
->
muxer
);
matroska_uninit
(
&
obj
->
file
);
for
(
i
=
0
;
i
<
f
->
desc
->
ninputs
;
i
++
)
{
if
(
obj
->
modulesList
[
i
]
!=
NULL
)
module_free
(
obj
->
modulesList
[
i
]);
...
...
@@ -1674,7 +1678,6 @@ static inline void changeClockRate(mblk_t *buffer, unsigned int oldClockRate, un
static
int
recorder_open_file
(
MSFilter
*
f
,
void
*
arg
)
{
MKVRecorder
*
obj
=
(
MKVRecorder
*
)
f
->
data
;
const
char
*
filename
=
(
const
char
*
)
arg
;
int
i
;
ms_filter_lock
(
f
);
if
(
obj
->
state
!=
MSRecorderClosed
)
{
...
...
@@ -1687,45 +1690,13 @@ static int recorder_open_file(MSFilter *f, void *arg) {
obj
->
openMode
=
MKV_OPEN_CREATE
;
}
ms_message
(
"MKVRecor
e
der: opening file %s in %s mode"
,
filename
,
obj
->
openMode
==
MKV_OPEN_APPEND
?
"append"
:
"create"
);
ms_message
(
"MKVRecorder: opening file %s in %s mode"
,
filename
,
obj
->
openMode
==
MKV_OPEN_APPEND
?
"append"
:
"create"
);
if
(
matroska_open_file
(
&
obj
->
file
,
filename
,
obj
->
openMode
)
!=
0
)
{
ms_error
(
"MKVRecorder: fail to open %s"
,
filename
);
goto
fail
;
}
if
(
obj
->
openMode
==
MKV_OPEN_CREATE
)
{
matroska_set_doctype_version
(
&
obj
->
file
,
MKV_DOCTYPE_VERSION
,
MKV_DOCTYPE_READ_VERSION
);
matroska_write_ebml_header
(
&
obj
->
file
);
matroska_start_segment
(
&
obj
->
file
);
matroska_write_zeros
(
&
obj
->
file
,
1024
);
matroska_mark_segment_info_position
(
&
obj
->
file
);
matroska_write_zeros
(
&
obj
->
file
,
1024
);
for
(
i
=
0
;
i
<
f
->
desc
->
ninputs
;
i
++
)
{
if
(
obj
->
inputDescsList
[
i
]
!=
NULL
)
{
obj
->
modulesList
[
i
]
=
module_new
(
obj
->
inputDescsList
[
i
]
->
encoding
);
module_set
(
obj
->
modulesList
[
i
],
obj
->
inputDescsList
[
i
]);
matroska_add_track
(
&
obj
->
file
,
i
+
1
,
module_get_codec_id
(
obj
->
modulesList
[
i
]));
obj
->
timeLoopCancelers
[
i
]
=
time_loop_canceler_new
();
}
}
obj
->
duration
=
0
;
}
else
{
for
(
i
=
0
;
i
<
f
->
desc
->
ninputs
;
i
++
)
{
if
(
obj
->
inputDescsList
[
i
]
!=
NULL
)
{
const
uint8_t
*
data
=
NULL
;
size_t
length
;
obj
->
modulesList
[
i
]
=
module_new
(
obj
->
inputDescsList
[
i
]
->
encoding
);
module_set
(
obj
->
modulesList
[
i
],
obj
->
inputDescsList
[
i
]);
if
(
matroska_get_codec_private
(
&
obj
->
file
,
i
+
1
,
&
data
,
&
length
)
==
0
)
{
module_load_private_data
(
obj
->
modulesList
[
i
],
data
,
length
);
}
obj
->
timeLoopCancelers
[
i
]
=
time_loop_canceler_new
();
}
}
obj
->
duration
=
matroska_get_duration
(
&
obj
->
file
);
}
time_corrector_set_origin
(
&
obj
->
timeCorrector
,
obj
->
duration
);
obj
->
state
=
MSRecorderPaused
;
ms_filter_unlock
(
f
);
return
0
;
...
...
@@ -1737,11 +1708,49 @@ static int recorder_open_file(MSFilter *f, void *arg) {
static
int
recorder_start
(
MSFilter
*
f
,
void
*
arg
)
{
MKVRecorder
*
obj
=
(
MKVRecorder
*
)
f
->
data
;
int
i
;
ms_filter_lock
(
f
);
if
(
obj
->
state
==
MSRecorderClosed
)
{
ms_error
(
"MKVRecorder: fail to start recording. The file has not been opened"
);
goto
fail
;
}
if
(
!
obj
->
tracksInitialized
){
if
(
obj
->
openMode
==
MKV_OPEN_CREATE
)
{
matroska_set_doctype_version
(
&
obj
->
file
,
MKV_DOCTYPE_VERSION
,
MKV_DOCTYPE_READ_VERSION
);
matroska_write_ebml_header
(
&
obj
->
file
);
matroska_start_segment
(
&
obj
->
file
);
matroska_write_zeros
(
&
obj
->
file
,
1024
);
matroska_mark_segment_info_position
(
&
obj
->
file
);
matroska_write_zeros
(
&
obj
->
file
,
1024
);
for
(
i
=
0
;
i
<
f
->
desc
->
ninputs
;
i
++
)
{
if
(
obj
->
inputDescsList
[
i
]
!=
NULL
)
{
obj
->
modulesList
[
i
]
=
module_new
(
obj
->
inputDescsList
[
i
]
->
encoding
);
module_set
(
obj
->
modulesList
[
i
],
obj
->
inputDescsList
[
i
]);
matroska_add_track
(
&
obj
->
file
,
i
+
1
,
module_get_codec_id
(
obj
->
modulesList
[
i
]));
obj
->
timeLoopCancelers
[
i
]
=
time_loop_canceler_new
();
}
}
obj
->
duration
=
0
;
}
else
{
for
(
i
=
0
;
i
<
f
->
desc
->
ninputs
;
i
++
)
{
if
(
obj
->
inputDescsList
[
i
]
!=
NULL
)
{
const
uint8_t
*
data
=
NULL
;
size_t
length
;
obj
->
modulesList
[
i
]
=
module_new
(
obj
->
inputDescsList
[
i
]
->
encoding
);
module_set
(
obj
->
modulesList
[
i
],
obj
->
inputDescsList
[
i
]);
if
(
matroska_get_codec_private
(
&
obj
->
file
,
i
+
1
,
&
data
,
&
length
)
==
0
)
{
module_load_private_data
(
obj
->
modulesList
[
i
],
data
,
length
);
}
obj
->
timeLoopCancelers
[
i
]
=
time_loop_canceler_new
();
}
}
obj
->
duration
=
matroska_get_duration
(
&
obj
->
file
);
}
time_corrector_set_origin
(
&
obj
->
timeCorrector
,
obj
->
duration
);
obj
->
tracksInitialized
=
TRUE
;
}
obj
->
state
=
MSRecorderRunning
;
obj
->
needKeyFrame
=
TRUE
;
ms_message
(
"MKVRecorder: recording successfully started"
);
...
...
@@ -1777,6 +1786,13 @@ static int recorder_stop(MSFilter *f, void *arg) {
return
-
1
;
}
static
void
recorder_request_fir
(
MSFilter
*
f
,
MKVRecorder
*
obj
){
if
(
obj
->
lastFirTime
==
-
1
||
obj
->
lastFirTime
+
2000
<
f
->
ticker
->
time
){
obj
->
lastFirTime
=
f
->
ticker
->
time
;
ms_filter_notify_no_arg
(
f
,
MS_RECORDER_NEEDS_FIR
);
}
}
static
void
recorder_process
(
MSFilter
*
f
)
{
MKVRecorder
*
obj
=
f
->
data
;
int
i
;
...
...
@@ -1808,13 +1824,14 @@ static void recorder_process(MSFilter *f) {
if
(
obj
->
inputDescsList
[
i
]
->
type
==
MSVideo
&&
obj
->
needKeyFrame
)
{
while
((
buffer
=
ms_queue_get
(
&
frames_ms
))
!=
NULL
)
{
if
(
module_is_key_frame
(
obj
->
modulesList
[
i
],
buffer
))
{
if
(
module_is_key_frame
(
obj
->
modulesList
[
i
],
buffer
))
{
break
;
}
else
{
recorder_request_fir
(
f
,
obj
);
freemsg
(
buffer
);
}
}
if
(
buffer
!=
NULL
)
{
if
(
buffer
!=
NULL
)
{
do
{
time_corrector_proceed
(
&
obj
->
timeCorrector
,
buffer
,
i
);
muxer_put_buffer
(
&
obj
->
muxer
,
buffer
,
i
);
...
...
@@ -1903,6 +1920,7 @@ static int recorder_close(MSFilter *f, void *arg) {
}
else
{
ms_warning
(
"MKVRecorder: no file has been opened"
);
}
obj
->
tracksInitialized
=
FALSE
;
ms_filter_unlock
(
f
);
return
0
;
...
...
@@ -1919,23 +1937,26 @@ static int recorder_set_input_fmt(MSFilter *f, void *arg) {
}
if
(
data
->
state
!=
MSRecorderClosed
)
{
if
(
pinFmt
->
fmt
==
NULL
)
{
ms_error
(
"MKVRecorder: could not disable pin #%d. The file is opened"
,
pinFmt
->
pin
);
goto
fail
;
}
if
(
data
->
inputDescsList
[
pinFmt
->
pin
]
==
NULL
)
{
ms_error
(
"MKVRecorder: could not set pin #%d video size. That pin is not enabled"
,
pinFmt
->
pin
);
goto
fail
;
}
if
(
pinFmt
->
fmt
->
type
!=
MSVideo
||
if
(
data
->
tracksInitialized
){
if
(
pinFmt
->
fmt
==
NULL
)
{
ms_error
(
"MKVRecorder: could not disable pin #%d. The file is opened"
,
pinFmt
->
pin
);
goto
fail
;
}
if
(
data
->
inputDescsList
[
pinFmt
->
pin
]
==
NULL
)
{
ms_error
(
"MKVRecorder: could not set pin #%d video size. That pin is not enabled"
,
pinFmt
->
pin
);
goto
fail
;
}
if
(
pinFmt
->
fmt
->
type
!=
MSVideo
||
strcmp
(
pinFmt
->
fmt
->
encoding
,
data
->
inputDescsList
[
pinFmt
->
pin
]
->
encoding
)
!=
0
||
pinFmt
->
fmt
->
rate
!=
data
->
inputDescsList
[
pinFmt
->
pin
]
->
rate
)
{
ms_error
(
"MKVRecorder: could not set pin #%d video size. The specified format is not compatible with the current format. current={%s}, new={%s}"
,
ms_error
(
"MKVRecorder: could not set pin #%d video size. The specified format is not compatible with the current format. current={%s}, new={%s}"
,
pinFmt
->
pin
,
ms_fmt_descriptor_to_string
(
data
->
inputDescsList
[
pinFmt
->
pin
]),
ms_fmt_descriptor_to_string
(
pinFmt
->
fmt
));
goto
fail
;
goto
fail
;
}
}
data
->
inputDescsList
[
pinFmt
->
pin
]
=
pinFmt
->
fmt
;
ms_message
(
"MKVRecorder: pin #%d video size set on %dx%d"
,
pinFmt
->
pin
,
pinFmt
->
fmt
->
vsize
.
width
,
pinFmt
->
fmt
->
vsize
.
height
);
}
else
{
...
...
src/voip/videostream.c
View file @
ba56966d
...
...
@@ -648,7 +648,7 @@ static void video_stream_payload_type_changed(RtpSession *session, void *data){
int
video_stream_start
(
VideoStream
*
stream
,
RtpProfile
*
profile
,
const
char
*
rem_rtp_ip
,
int
rem_rtp_port
,
const
char
*
rem_rtcp_ip
,
int
rem_rtcp_port
,
int
payload
,
int
jitt_comp
,
MSWebCam
*
cam
){
MSMediaStreamIO
io
=
MS_MEDIA_STREAM_IO_INITIALIZER
;
if
(
cam
==
NULL
){
if
(
cam
==
NULL
){
cam
=
ms_web_cam_manager_get_default_cam
(
ms_web_cam_manager_get
()
);
}
io
.
input
.
type
=
MSResourceCamera
;
...
...
@@ -659,6 +659,16 @@ int video_stream_start (VideoStream *stream, RtpProfile *profile, const char *re
return
video_stream_start_from_io
(
stream
,
profile
,
rem_rtp_ip
,
rem_rtp_port
,
rem_rtcp_ip
,
rem_rtcp_port
,
payload
,
&
io
);
}
static
void
recorder_handle_event
(
void
*
userdata
,
MSFilter
*
recorder
,
unsigned
int
event
,
void
*
event_arg
){
VideoStream
*
stream
=
(
VideoStream
*
)
userdata
;
switch
(
event
){
case
MS_RECORDER_NEEDS_FIR
:
ms_message
(
"Request sending of FIR on videostream [%p]"
,
stream
);
video_stream_send_fir
(
stream
);
break
;
}
}
int
video_stream_start_from_io
(
VideoStream
*
stream
,
RtpProfile
*
profile
,
const
char
*
rem_rtp_ip
,
int
rem_rtp_port
,
const
char
*
rem_rtcp_ip
,
int
rem_rtcp_port
,
int
payload
,
const
MSMediaStreamIO
*
io
)
{
MSWebCam
*
cam
=
NULL
;
...
...
@@ -715,6 +725,8 @@ int video_stream_start_from_io(VideoStream *stream, RtpProfile *profile, const c
ms_filter_destroy
(
stream
->
recorder_output
);
}
stream
->
recorder_output
=
recorder
;
ms_filter_add_notify_callback
(
recorder
,
recorder_handle_event
,
stream
,
TRUE
);
if
(
io
->
output
.
file
)
video_stream_open_remote_record
(
stream
,
io
->
output
.
file
);
break
;
default:
/*will just display in all other cases*/
...
...
@@ -1063,6 +1075,15 @@ static int video_stream_start_with_source_and_output(VideoStream *stream, RtpPro
stream
->
ms
.
voidsink
=
ms_filter_new
(
MS_VOID_SINK_ID
);
ms_filter_link
(
stream
->
ms
.
rtprecv
,
0
,
stream
->
ms
.
voidsink
,
0
);
}
/*start the video recorder if it was opened previously*/
if
(
stream
->
recorder_output
&&
ms_filter_implements_interface
(
stream
->
recorder_output
,
MSFilterRecorderInterface
)){
MSRecorderState
state
=
MSRecorderClosed
;
ms_filter_call_method
(
stream
->
recorder_output
,
MS_RECORDER_GET_STATE
,
&
state
);
if
(
state
==
MSRecorderPaused
){
ms_filter_call_method_noarg
(
stream
->
recorder_output
,
MS_RECORDER_START
);
}
}
/* create the ticker */
if
(
stream
->
ms
.
sessions
.
ticker
==
NULL
)
media_stream_start_ticker
(
&
stream
->
ms
);
...
...
@@ -1357,6 +1378,15 @@ static MSFilter* _video_stream_stop(VideoStream * stream, bool_t keep_source)
rtp_session_set_rtcp_xr_media_callbacks
(
stream
->
ms
.
sessions
.
rtp_session
,
NULL
);
rtp_session_signal_disconnect_by_callback
(
stream
->
ms
.
sessions
.
rtp_session
,
"payload_type_changed"
,(
RtpCallback
)
video_stream_payload_type_changed
);
/*Automatically the video recorder if it was opened previously*/
if
(
stream
->
recorder_output
&&
ms_filter_implements_interface
(
stream
->
recorder_output
,
MSFilterRecorderInterface
)){
MSRecorderState
state
=
MSRecorderClosed
;
ms_filter_call_method
(
stream
->
recorder_output
,
MS_RECORDER_GET_STATE
,
&
state
);
if
(
state
!=
MSRecorderClosed
){
ms_filter_call_method_noarg
(
stream
->
recorder_output
,
MS_RECORDER_CLOSE
);
}
}
if
(
keep_source
){
source
=
stream
->
source
;
stream
->
source
=
NULL
;
// will prevent video_stream_free() from destroying the source
...
...
@@ -1628,17 +1658,29 @@ void video_stream_close_remote_play(VideoStream *stream){
}
}
int
video_stream_remote_record_open
(
VideoStream
*
stream
,
const
char
*
filename
){
/*stub, to be implemented.*/
return
-
1
;
}
int
video_stream_remote_record_start
(
VideoStream
*
stream
){
/*stub, to be implemented.*/
return
-
1
;
MSFilter
*
video_stream_open_remote_record
(
VideoStream
*
stream
,
const
char
*
filename
){
MSFilter
*
recorder
=
stream
->
recorder_output
;
if
(
!
recorder
||
!
ms_filter_implements_interface
(
recorder
,
MSFilterRecorderInterface
)){
ms_error
(
"video_stream_open_remote_play(): the stream is not using a recorder."
);
return
NULL
;
}
if
(
ms_filter_call_method
(
recorder
,
MS_RECORDER_OPEN
,
(
void
*
)
filename
)
!=
0
){
return
NULL
;
}
return
recorder
;
}
int
video_stream_remote_record_stop
(
VideoStream
*
stream
){
/*stub, to be implemented.*/
return
-
1
;
void
video_stream_close_remote_record
(
VideoStream
*
stream
){
MSFilter
*
recorder
=
stream
->
recorder_output
;
MSRecorderState
state
=
MSRecorderClosed
;
if
(
!
recorder
||
!
ms_filter_implements_interface
(
recorder
,
MSFilterRecorderInterface
)){
ms_error
(
"video_stream_close_remote_record(): the stream is not using a recorder."
);
return
;
}
ms_filter_call_method
(
recorder
,
MS_RECORDER_GET_STATE
,
&
state
);
if
(
state
!=
MSRecorderClosed
){
ms_filter_call_method_noarg
(
recorder
,
MS_RECORDER_CLOSE
);
}
}
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