Commit 9c9d8804 authored by Ghislain MARY's avatar Ghislain MARY

Add option to choose between freezing or not on VP8 decoding error.

parent e045e7b0
......@@ -575,6 +575,7 @@ struct _VideoStream
MSWebCam *cam;
int device_orientation; /* warning: meaning of this variable depends on the platform (Android, iOS, ...) */
bool_t use_preview_window;
bool_t freeze_on_error;
bool_t display_filter_auto_rotate_enabled;
bool_t source_performs_encoding;
bool_t output_performs_decoding;
......@@ -655,6 +656,7 @@ MS2_PUBLIC unsigned long video_stream_get_native_preview_window_id(VideoStream *
MS2_PUBLIC void video_stream_use_preview_video_window(VideoStream *stream, bool_t yesno);
MS2_PUBLIC void video_stream_set_device_rotation(VideoStream *stream, int orientation);
MS2_PUBLIC void video_stream_show_video(VideoStream *stream, bool_t show);
MS2_PUBLIC void video_stream_set_freeze_on_error(VideoStream *stream, bool_t yesno);
/**
* @brief Gets the camera sensor rotation.
......
......@@ -213,6 +213,8 @@ typedef enum _MSRecorderState MSRecorderState;
MS_FILTER_METHOD(MSFilterVideoDecoderInterface, 6, bool_t)
#define MS_VIDEO_DECODER_SUPPORT_RENDERING \
MS_FILTER_METHOD(MSFilterVideoDecoderInterface, 7, MSVideoDisplayDecodingSupport*)
#define MS_VIDEO_DECODER_FREEZE_ON_ERROR \
MS_FILTER_METHOD(MSFilterVideoDecoderInterface, 8, bool_t)
/** Interface definitions for video capture */
#define MS_VIDEO_CAPTURE_SET_DEVICE_ORIENTATION \
......
......@@ -733,6 +733,7 @@ typedef struct DecState {
MSAverageFPS fps;
bool_t first_image_decoded;
bool_t avpf_enabled;
bool_t freeze_on_error;
} DecState;
......@@ -750,6 +751,7 @@ static void dec_init(MSFilter *f) {
ms_queue_init(&s->q);
s->first_image_decoded = FALSE;
s->avpf_enabled = FALSE;
s->freeze_on_error = FALSE;
f->data = s;
ms_video_init_average_fps(&s->fps, "VP8 decoder: FPS: %f");
}
......@@ -774,7 +776,7 @@ static void dec_preprocess(MSFilter* f) {
if(vpx_codec_dec_init(&s->codec, s->iface, NULL, s->flags))
ms_error("Failed to initialize decoder");
vp8rtpfmt_unpacker_init(&s->unpacker, f, s->avpf_enabled, (s->flags & VPX_CODEC_USE_INPUT_FRAGMENTS) ? TRUE : FALSE);
vp8rtpfmt_unpacker_init(&s->unpacker, f, s->avpf_enabled, s->freeze_on_error, (s->flags & VPX_CODEC_USE_INPUT_FRAGMENTS) ? TRUE : FALSE);
s->first_image_decoded = FALSE;
}
......@@ -869,6 +871,12 @@ static int dec_enable_avpf(MSFilter *f, void *data) {
return 0;
}
static int dec_freeze_on_error(MSFilter *f, void *data) {
DecState *s = (DecState *)f->data;
s->freeze_on_error = *((bool_t *)data) ? TRUE : FALSE;
return 0;
}
static int dec_get_vsize(MSFilter *f, void *data) {
DecState *s = (DecState *)f->data;
MSVideoSize *vsize = (MSVideoSize *)data;
......@@ -885,6 +893,7 @@ static int dec_get_vsize(MSFilter *f, void *data) {
static MSFilterMethod dec_methods[] = {
{ MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION, dec_reset_first_image },
{ MS_VIDEO_DECODER_ENABLE_AVPF, dec_enable_avpf },
{ MS_VIDEO_DECODER_FREEZE_ON_ERROR, dec_freeze_on_error },
{ MS_FILTER_GET_VIDEO_SIZE, dec_get_vsize },
{ 0, NULL }
};
......
......@@ -204,6 +204,7 @@ VideoStream *video_stream_new_with_sessions(const MSMediaStreamSessions *session
MS_VIDEO_SIZE_ASSIGN(stream->sent_vsize, CIF);
stream->dir=VideoStreamSendRecv;
stream->display_filter_auto_rotate_enabled=0;
stream->freeze_on_error = FALSE;
stream->source_performs_encoding = FALSE;
stream->output_performs_decoding = FALSE;
choose_display_name(stream);
......@@ -555,6 +556,7 @@ int video_stream_start (VideoStream *stream, RtpProfile *profile, const char *re
if (pt->recv_fmtp!=NULL)
ms_filter_call_method(stream->ms.decoder,MS_FILTER_ADD_FMTP,(void*)pt->recv_fmtp);
ms_filter_call_method(stream->ms.decoder, MS_VIDEO_DECODER_ENABLE_AVPF, &avpf_enabled);
ms_filter_call_method(stream->ms.decoder, MS_VIDEO_DECODER_FREEZE_ON_ERROR, &stream->freeze_on_error);
/*force the decoder to output YUV420P */
format=MS_YUV420P;
......@@ -850,6 +852,10 @@ void video_stream_set_device_rotation(VideoStream *stream, int orientation){
stream->device_orientation = orientation;
}
void video_stream_set_freeze_on_error(VideoStream *stream, bool_t yesno) {
stream->freeze_on_error = yesno;
}
int video_stream_get_camera_sensor_rotation(VideoStream *stream) {
int rotation = -1;
if (stream->source) {
......
......@@ -24,7 +24,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <limits.h>
#define VP8RTPFMT_OUTPUT_INCOMPLETE_PARTITIONS
/*#define VP8RTPFMT_DEBUG*/
#if (defined(__GNUC__) && __GNUC__) || defined(__SUNPRO_C)
......@@ -308,6 +307,11 @@ static bool_t parse_frame_header(Vp8RtpFmtFrame *frame) {
nb_partitions = (1 << vp8_read_literal(&bc, 2));
if (nb_partitions > 8) return FALSE;
frame->partitions_info.nb_partitions = nb_partitions;
if (nb_partitions == 1) {
/* Special case when partitioning is not enabled. */
frame->partitions_info.partition_sizes[0] = m->b_wptr - m->b_rptr;
return TRUE;
}
partition_size = data + first_partition_length_in_bytes - m->b_rptr + (3 * (nb_partitions - 1));
if (msgdsize(m) != partition_size) return FALSE;
frame->partitions_info.partition_sizes[0] = partition_size;
......@@ -517,7 +521,7 @@ static void mark_frame_as_invalid(Vp8RtpFmtUnpackerCtx *ctx, Vp8RtpFmtFrame *fra
static void mark_frame_as_incomplete(Vp8RtpFmtUnpackerCtx *ctx, Vp8RtpFmtFrame *frame, uint8_t idx) {
frame->error = Vp8RtpFmtIncompleteFrame;
if (ctx->output_partitions != TRUE) {
if (ctx->freeze_on_error == TRUE) {
ctx->waiting_for_reference_frame = TRUE;
}
}
......@@ -567,7 +571,7 @@ static void check_frame_partitions_list(Vp8RtpFmtUnpackerCtx *ctx, Vp8RtpFmtFram
}
/* Check the last partition of the frame. */
if (frame->partitions_info.nb_partitions > 0) {
if (frame->partitions_info.nb_partitions > 1) {
partition = frame->partitions[frame->partitions_info.nb_partitions];
if ((partition == NULL) || !partition->has_start || !partition->has_marker) {
mark_frame_as_incomplete(ctx, frame, frame->partitions_info.nb_partitions - 1);
......@@ -691,6 +695,7 @@ static void output_frame(MSQueue *out, Vp8RtpFmtFrame *frame) {
for (i = 0; i <= frame->partitions_info.nb_partitions; i++) {
partition = frame->partitions[i];
if (partition == NULL) continue;
if (i == 0) {
om = partition->m;
curm = om;
......@@ -756,13 +761,10 @@ static void output_valid_partitions(Vp8RtpFmtUnpackerCtx *ctx, MSQueue *out) {
/* Incomplete keyframe. */
frame->discarded = TRUE;
} else {
#ifdef VP8RTPFMT_OUTPUT_INCOMPLETE_PARTITIONS
if ((ctx->output_partitions == TRUE) && (ctx->valid_keyframe_received == TRUE) && (ctx->waiting_for_reference_frame == FALSE)) {
output_partitions_of_frame(ctx, out, frame);
frame->outputted = TRUE;
} else
#endif
{
} else {
/* Drop the frame for which some partitions are missing/invalid. */
#ifdef VP8RTPFMT_DEBUG
if (frame->pictureid_present == TRUE)
......@@ -879,12 +881,13 @@ static Vp8RtpFmtErrorCode parse_payload_descriptor(Vp8RtpFmtPacket *packet) {
}
void vp8rtpfmt_unpacker_init(Vp8RtpFmtUnpackerCtx *ctx, MSFilter *f, bool_t avpf_enabled, bool_t output_partitions) {
void vp8rtpfmt_unpacker_init(Vp8RtpFmtUnpackerCtx *ctx, MSFilter *f, bool_t avpf_enabled, bool_t freeze_on_error, bool_t output_partitions) {
ctx->filter = f;
ctx->frames_list = NULL;
ctx->non_processed_packets_list = NULL;
ms_queue_init(&ctx->output_queue);
ctx->avpf_enabled = avpf_enabled;
ctx->freeze_on_error = freeze_on_error;
ctx->output_partitions = output_partitions;
ctx->valid_keyframe_received = FALSE;
ctx->waiting_for_reference_frame = TRUE;
......
......@@ -102,6 +102,7 @@ extern "C"{
uint32_t last_ts;
uint32_t ref_cseq;
bool_t avpf_enabled;
bool_t freeze_on_error;
bool_t output_partitions;
bool_t waiting_for_reference_frame;
bool_t valid_keyframe_received;
......@@ -118,7 +119,7 @@ extern "C"{
void vp8rtpfmt_packer_uninit(Vp8RtpFmtPackerCtx *ctx);
void vp8rtpfmt_packer_process(Vp8RtpFmtPackerCtx *ctx, MSList *in, MSQueue *out);
void vp8rtpfmt_unpacker_init(Vp8RtpFmtUnpackerCtx *ctx, MSFilter *f, bool_t avpf_enabled, bool_t output_partitions);
void vp8rtpfmt_unpacker_init(Vp8RtpFmtUnpackerCtx *ctx, MSFilter *f, bool_t avpf_enabled, bool_t freeze_on_error, bool_t output_partitions);
void vp8rtpfmt_unpacker_uninit(Vp8RtpFmtUnpackerCtx *ctx);
void vp8rtpfmt_unpacker_process(Vp8RtpFmtUnpackerCtx *ctx, MSQueue *inout);
uint32_t vp8rtpfmt_unpacker_calc_extended_cseq(Vp8RtpFmtUnpackerCtx *ctx, uint16_t cseq);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment