|
From: | jim |
Subject: | [Linphone-developers] Please help on how to get last successfully decoded frame for application to display while the the current frame is corrupt when decoding in dec_process |
Date: | Fri, 15 May 2015 09:35:35 +0800 |
Hi experts,
This is Jim and I am using linphone for a voip project. To improve the user experience for video , I want to make some change in the mediastream2 layer: if we find the current frame is corrupt, just use the last successfully decoded frame to display.
I try this way for vp8 in vp8.c, the line in blue is what I add :
=====================================
static mblk_t *dec_last_successfully_decoded_frame = NULL;
static void dec_process(MSFilter *f) {
mblk_t *im;
DecState *s=(DecState*)f->data;
while( (im=ms_queue_get(f->inputs[0]))!=0) {
mblk_t *m;
dec_unpacketize(f, s, im, &s->q);
while((m=ms_queue_get(&s->q))!=NULL){
vpx_codec_err_t err;
vpx_codec_iter_t iter = NULL;
vpx_image_t *img;
err = vpx_codec_decode(&s->codec, m->b_rptr, m->b_wptr - m->b_rptr, NULL, 0);
if (err) {
ms_warning("vpx_codec_decode failed : %d %s (%s)\n", err, vpx_codec_err_to_string(err), vpx_codec_error_detail(&s->codec));
if ((f->ticker->time - s->last_error_reported_time)>5000 || s->last_error_reported_time==0) {
s->last_error_reported_time=f->ticker->time;
ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_DECODING_ERRORS);
}
if (s->first_image_decoded == FALSE) {
/* if no frames have been decoded yet, do not try to browse decoded frames */
freemsg(m);
continue;
}
if (VPX_CODEC_CORRUPT_FRAME == err||VPX_CODEC_UNSUP_BITSTREAM == err) {
/* do not try to browse decoded frames, use last successfully decoded frame instead */
if (dec_last_successfully_decoded_frame) {
ms_queue_put(f->outputs[0], dec_last_successfully_decoded_frame);
}
freemsg(m);
continue;
}
}
/* browse decoded frames */
while((img = vpx_codec_get_frame(&s->codec, &iter))) {
int i,j;
if (s->yuv_width != img->d_w || s->yuv_height != img->d_h) {
if (s->yuv_msg)
freemsg(s->yuv_msg);
s->yuv_msg = ms_yuv_buf_alloc(&s->outbuf, img->d_w, img->d_h);
s->yuv_width = img->d_w;
s->yuv_height = img->d_h;
}
/* scale/copy frame to destination mblk_t */
for(i=0; i<3; i++) {
uint8_t* dest = s->outbuf.planes[i];
uint8_t* src = "">
int h = img->d_h >> ((i>0)?1:0);
for(j=0; j<h; j++) {
memcpy(dest, src, s->outbuf.strides[i]);
dest += s->outbuf.strides[i];
src += img->stride[i];
}
}
//ms_queue_put(f->outputs[0], dupmsg(s->yuv_msg));
if (dec_last_successfully_decoded_frame) {
free(dec_last_successfully_decoded_frame);
dec_last_successfully_decoded_frame = NULL;
}
ms_queue_put(f->outputs[0], dupmsg(s->yuv_msg));
dec_last_successfully_decoded_frame = dupmsg(s->yuv_msg);
if (ms_video_update_average_fps(&s->fps, f->ticker->time)) {
ms_message("VP8 decoder: Frame size: %dx%d", s->yuv_width, s->yuv_height);
}
if (!s->first_image_decoded) {
s->first_image_decoded = TRUE;
ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_FIRST_IMAGE_DECODED);
}
//}
}
freemsg(m);
}
}
}
[Prev in Thread] | Current Thread | [Next in Thread] |