summaryrefslogtreecommitdiff
path: root/pjmedia/src/pjmedia-videodev
diff options
context:
space:
mode:
authorLiong Sauw Ming <ming@teluu.com>2012-04-10 11:54:04 +0000
committerLiong Sauw Ming <ming@teluu.com>2012-04-10 11:54:04 +0000
commit1e3cebce45a4f3b897493c1ad2d4bc97109fae2b (patch)
tree2005a6f0a8f56f9609921fbdea6d806ed33d3470 /pjmedia/src/pjmedia-videodev
parent9d63100da3106243acc96f97c7f198c7e245f1f6 (diff)
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
Diffstat (limited to 'pjmedia/src/pjmedia-videodev')
-rw-r--r--pjmedia/src/pjmedia-videodev/avi_dev.c87
1 files changed, 83 insertions, 4 deletions
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 <pj/log.h>
#include <pj/os.h>
#include <pj/rand.h>
+#include <pjmedia/vid_codec.h>
#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(&param->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(&param->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);