From 1e3cebce45a4f3b897493c1ad2d4bc97109fae2b Mon Sep 17 00:00:00 2001 From: Liong Sauw Ming Date: Tue, 10 Apr 2012 11:54:04 +0000 Subject: Re #1478: Add support to play encoded AVI file (H264 or MPEG4). git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4034 74dad513-b988-da41-8d7b-12977e46ad98 --- pjmedia/src/pjmedia-videodev/avi_dev.c | 87 ++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 4 deletions(-) (limited to 'pjmedia/src/pjmedia-videodev') diff --git a/pjmedia/src/pjmedia-videodev/avi_dev.c b/pjmedia/src/pjmedia-videodev/avi_dev.c index 770f4f25..478254d4 100644 --- a/pjmedia/src/pjmedia-videodev/avi_dev.c +++ b/pjmedia/src/pjmedia-videodev/avi_dev.c @@ -22,6 +22,7 @@ #include #include #include +#include #if defined(PJMEDIA_VIDEO_DEV_HAS_AVI) && PJMEDIA_VIDEO_DEV_HAS_AVI != 0 @@ -68,6 +69,9 @@ struct avi_dev_strm pjmedia_vid_dev_cb vid_cb; /**< Stream callback. */ void *user_data; /**< Application data. */ + pjmedia_vid_codec *codec; + pj_uint8_t *enc_buf; + pj_size_t enc_buf_size; }; @@ -432,7 +436,7 @@ PJ_DEF(pj_status_t) pjmedia_avi_dev_alloc( pjmedia_vid_dev_factory *f, adi->info.caps = PJMEDIA_VID_DEV_CAP_FORMAT; adi->info.fmt_cnt = 1; - adi->info.fmt[0] = adi->vid->info.fmt; + pjmedia_format_copy(&adi->info.fmt[0], &adi->vid->info.fmt); /* Set out vars */ if (p_id) @@ -465,6 +469,9 @@ static pj_status_t avi_factory_create_stream( pj_pool_t *pool = NULL; struct avi_dev_info *adi; struct avi_dev_strm *strm; + pjmedia_format avi_fmt; + const pjmedia_video_format_info *vfi; + pj_status_t status = PJ_SUCCESS; PJ_ASSERT_RETURN(f && param && p_vid_strm, PJ_EINVAL); PJ_ASSERT_RETURN(param->fmt.type == PJMEDIA_TYPE_VIDEO && @@ -490,8 +497,56 @@ static pj_status_t avi_factory_create_stream( strm->user_data = user_data; strm->adi = adi; - /* Override format (hack?) */ - pj_memcpy(¶m->fmt, &adi->vid->info.fmt, sizeof(pjmedia_format)); + pjmedia_format_copy(&avi_fmt, &adi->vid->info.fmt); + vfi = pjmedia_get_video_format_info(NULL, avi_fmt.id); + /* Check whether the frame is encoded. */ + if (!vfi || vfi->bpp == 0) { + /* Yes, prepare codec */ + const pjmedia_vid_codec_info *codec_info; + pjmedia_vid_codec_param codec_param; + pjmedia_video_apply_fmt_param vafp; + + /* Lookup codec */ + status = pjmedia_vid_codec_mgr_get_codec_info2(NULL, + avi_fmt.id, + &codec_info); + if (status != PJ_SUCCESS || !codec_info) + goto on_error; + + status = pjmedia_vid_codec_mgr_get_default_param(NULL, codec_info, + &codec_param); + if (status != PJ_SUCCESS) + goto on_error; + + /* Open codec */ + status = pjmedia_vid_codec_mgr_alloc_codec(NULL, codec_info, + &strm->codec); + if (status != PJ_SUCCESS) + goto on_error; + + status = pjmedia_vid_codec_init(strm->codec, strm->pool); + if (status != PJ_SUCCESS) + goto on_error; + + codec_param.dir = PJMEDIA_DIR_DECODING; + codec_param.packing = PJMEDIA_VID_PACKING_WHOLE; + status = pjmedia_vid_codec_open(strm->codec, &codec_param); + if (status != PJ_SUCCESS) + goto on_error; + + /* Allocate buffer */ + avi_fmt.id = codec_info->dec_fmt_id[0]; + vfi = pjmedia_get_video_format_info(NULL, avi_fmt.id); + pj_bzero(&vafp, sizeof(vafp)); + vafp.size = avi_fmt.det.vid.size; + status = vfi->apply_fmt(vfi, &vafp); + if (status != PJ_SUCCESS) + goto on_error; + + strm->enc_buf = pj_pool_alloc(strm->pool, vafp.framebytes); + strm->enc_buf_size = vafp.framebytes; + } + pjmedia_format_copy(¶m->fmt, &avi_fmt); /* Done */ strm->base.op = &stream_op; @@ -499,6 +554,10 @@ static pj_status_t avi_factory_create_stream( *p_vid_strm = &strm->base; return PJ_SUCCESS; + +on_error: + avi_dev_strm_destroy(&strm->base); + return status; } /* API: Get stream info. */ @@ -551,7 +610,22 @@ static pj_status_t avi_dev_strm_get_frame(pjmedia_vid_dev_stream *strm, pjmedia_frame *frame) { struct avi_dev_strm *stream = (struct avi_dev_strm*)strm; - return pjmedia_port_get_frame(stream->adi->vid, frame); + + if (stream->codec) { + pjmedia_frame enc_frame; + pj_status_t status; + + enc_frame.buf = stream->enc_buf; + enc_frame.size = stream->enc_buf_size; + status = pjmedia_port_get_frame(stream->adi->vid, &enc_frame); + if (status != PJ_SUCCESS) + return status; + + return pjmedia_vid_codec_decode(stream->codec, 1, &enc_frame, + frame->size, frame); + } else { + return pjmedia_port_get_frame(stream->adi->vid, frame); + } } /* API: Start stream. */ @@ -588,6 +662,11 @@ static pj_status_t avi_dev_strm_destroy(pjmedia_vid_dev_stream *strm) avi_dev_strm_stop(strm); + if (stream->codec) { + pjmedia_vid_codec_close(stream->codec); + stream->codec = NULL; + } + stream->adi->strm = NULL; stream->adi = NULL; pj_pool_release(stream->pool); -- cgit v1.2.3