static pj_status_t create_file_player( pj_pool_t *pool, const char *file_name, pjmedia_port **p_play_port) { pjmedia_avi_streams *avi_streams; pjmedia_avi_stream *vid_stream; pjmedia_port *play_port; pj_status_t status; status = pjmedia_avi_player_create_streams(pool, file_name, 0, &avi_streams); if (status != PJ_SUCCESS) return status; vid_stream = pjmedia_avi_streams_get_stream_by_media(avi_streams, 0, PJMEDIA_TYPE_VIDEO); if (!vid_stream) return PJ_ENOTFOUND; play_port = pjmedia_avi_stream_get_port(vid_stream); pj_assert(play_port); *p_play_port = play_port; return PJ_SUCCESS; }
static int aviplay(pj_pool_t *pool, const char *fname) { pjmedia_vid_port *renderer=NULL; pjmedia_vid_port_param param; const pjmedia_video_format_info *vfi; pjmedia_video_format_detail *vfd; pjmedia_snd_port *snd_port = NULL; pj_status_t status; int rc = 0; pjmedia_avi_streams *avi_streams; pjmedia_avi_stream *vid_stream, *aud_stream; pjmedia_port *vid_port = NULL, *aud_port = NULL; pjmedia_vid_codec *codec=NULL; avi_port_t avi_port; pj_bzero(&avi_port, sizeof(avi_port)); status = pjmedia_avi_player_create_streams(pool, fname, 0, &avi_streams); if (status != PJ_SUCCESS) { PJ_PERROR(2,("", status, " Error playing %s", fname)); rc = 210; goto on_return; } vid_stream = pjmedia_avi_streams_get_stream_by_media(avi_streams, 0, PJMEDIA_TYPE_VIDEO); vid_port = pjmedia_avi_stream_get_port(vid_stream); if (vid_port) { pjmedia_vid_port_param_default(¶m); status = pjmedia_vid_dev_default_param(pool, PJMEDIA_VID_DEFAULT_RENDER_DEV, ¶m.vidparam); if (status != PJ_SUCCESS) { rc = 220; goto on_return; } /* Create renderer, set it to active */ param.active = PJ_TRUE; param.vidparam.dir = PJMEDIA_DIR_RENDER; vfd = pjmedia_format_get_video_format_detail(&vid_port->info.fmt, PJ_TRUE); pjmedia_format_init_video(¶m.vidparam.fmt, vid_port->info.fmt.id, vfd->size.w, vfd->size.h, vfd->fps.num, vfd->fps.denum); vfi = pjmedia_get_video_format_info( pjmedia_video_format_mgr_instance(), vid_port->info.fmt.id); /* Check whether the frame is encoded */ if (!vfi || vfi->bpp == 0) { /* Yes, prepare codec */ pj_str_t codec_id_st; unsigned info_cnt = 1, i, k; const pjmedia_vid_codec_info *codec_info; pj_str_t port_name = {"codec", 5}; pj_uint8_t *enc_buf = NULL; pj_size_t enc_buf_size = 0; pjmedia_vid_dev_info rdr_info; pjmedia_port codec_port; codec_port_data_t codec_port_data; pjmedia_vid_codec_param codec_param; struct codec_fmt *codecp = NULL; /* Lookup codec */ for (i = 0; i < sizeof(codec_fmts)/sizeof(codec_fmts[0]); i++) { if (vid_port->info.fmt.id == codec_fmts[i].pjmedia_id) { codecp = &codec_fmts[i]; break; } } if (!codecp) { rc = 242; goto on_return; } pj_cstr(&codec_id_st, codecp->codec_id); status = pjmedia_vid_codec_mgr_find_codecs_by_id(NULL, &codec_id_st, &info_cnt, &codec_info, NULL); if (status != PJ_SUCCESS) { rc = 245; goto on_return; } status = pjmedia_vid_codec_mgr_get_default_param(NULL, codec_info, &codec_param); if (status != PJ_SUCCESS) { rc = 246; goto on_return; } pjmedia_format_copy(&codec_param.enc_fmt, ¶m.vidparam.fmt); pjmedia_vid_dev_get_info(param.vidparam.rend_id, &rdr_info); for (i=0; i<codec_info->dec_fmt_id_cnt; ++i) { for (k=0; k<rdr_info.fmt_cnt; ++k) { if (codec_info->dec_fmt_id[i]==(int)rdr_info.fmt[k].id) { param.vidparam.fmt.id = codec_info->dec_fmt_id[i]; i = codec_info->dec_fmt_id_cnt; break; } } } /* Open codec */ status = pjmedia_vid_codec_mgr_alloc_codec(NULL, codec_info, &codec); if (status != PJ_SUCCESS) { rc = 250; goto on_return; } status = pjmedia_vid_codec_init(codec, pool); if (status != PJ_SUCCESS) { rc = 251; goto on_return; } pjmedia_format_copy(&codec_param.dec_fmt, ¶m.vidparam.fmt); codec_param.dir = PJMEDIA_DIR_DECODING; codec_param.packing = PJMEDIA_VID_PACKING_WHOLE; status = pjmedia_vid_codec_open(codec, &codec_param); if (status != PJ_SUCCESS) { rc = 252; goto on_return; } /* Alloc encoding buffer */ enc_buf_size = codec_param.dec_fmt.det.vid.size.w * codec_param.dec_fmt.det.vid.size.h * 4 + 16; /*< padding, just in case */ enc_buf = pj_pool_alloc(pool,enc_buf_size); /* Init codec port */ pj_bzero(&codec_port, sizeof(codec_port)); status = pjmedia_port_info_init2(&codec_port.info, &port_name, 0x1234, PJMEDIA_DIR_ENCODING, &codec_param.dec_fmt); if (status != PJ_SUCCESS) { rc = 260; goto on_return; } pj_bzero(&codec_port_data, sizeof(codec_port_data)); codec_port_data.codec = codec; codec_port_data.src_port = vid_port; codec_port_data.enc_buf = enc_buf; codec_port_data.enc_buf_size = enc_buf_size; codec_port.get_frame = &codec_get_frame; codec_port.port_data.pdata = &codec_port_data; /* Check whether we need to convert the decoded frame */ if (codecp->need_conversion) { pjmedia_conversion_param conv_param; pjmedia_format_copy(&conv_param.src, ¶m.vidparam.fmt); pjmedia_format_copy(&conv_param.dst, ¶m.vidparam.fmt); conv_param.dst.id = codecp->dst_fmt; param.vidparam.fmt.id = conv_param.dst.id; status = pjmedia_converter_create(NULL, pool, &conv_param, &codec_port_data.conv); if (status != PJ_SUCCESS) { rc = 270; goto on_return; } } status = pjmedia_vid_port_create(pool, ¶m, &renderer); if (status != PJ_SUCCESS) { rc = 230; goto on_return; } status = pjmedia_vid_port_connect(renderer, &codec_port, PJ_FALSE); } else { status = pjmedia_vid_port_create(pool, ¶m, &renderer); if (status != PJ_SUCCESS) { rc = 230; goto on_return; } /* Connect avi port to renderer */ status = pjmedia_vid_port_connect(renderer, vid_port, PJ_FALSE); } if (status != PJ_SUCCESS) { rc = 240; goto on_return; } } aud_stream = pjmedia_avi_streams_get_stream_by_media(avi_streams, 0, PJMEDIA_TYPE_AUDIO); aud_port = pjmedia_avi_stream_get_port(aud_stream); if (aud_port) { /* Create sound player port. */ status = pjmedia_snd_port_create_player( pool, /* pool */ -1, /* use default dev. */ PJMEDIA_PIA_SRATE(&aud_port->info),/* clock rate. */ PJMEDIA_PIA_CCNT(&aud_port->info), /* # of channels. */ PJMEDIA_PIA_SPF(&aud_port->info), /* samples per frame. */ PJMEDIA_PIA_BITS(&aud_port->info), /* bits per sample. */ 0, /* options */ &snd_port /* returned port */ ); if (status != PJ_SUCCESS) { rc = 310; goto on_return; } /* Connect file port to the sound player. * Stream playing will commence immediately. */ status = pjmedia_snd_port_connect(snd_port, aud_port); if (status != PJ_SUCCESS) { rc = 330; goto on_return; } } if (vid_port) { pjmedia_vid_dev_cb cb; pj_bzero(&cb, sizeof(cb)); avi_port.snd_port = snd_port; avi_port.vid_port = renderer; avi_port.is_running = PJ_TRUE; pjmedia_vid_port_set_cb(renderer, &cb, &avi_port); /* subscribe events */ pjmedia_event_subscribe(NULL, &avi_event_cb, &avi_port, renderer); if (snd_port) { /* Synchronize video rendering and audio playback */ pjmedia_vid_port_set_clock_src( renderer, pjmedia_snd_port_get_clock_src( snd_port, PJMEDIA_DIR_PLAYBACK)); } /* Start video streaming.. */ status = pjmedia_vid_port_start(renderer); if (status != PJ_SUCCESS) { rc = 270; goto on_return; } } while (!avi_port.is_quitting) { pj_thread_sleep(100); } on_return: if (snd_port) { pjmedia_snd_port_disconnect(snd_port); /* Without this sleep, Windows/DirectSound will repeteadly * play the last frame during destroy. */ pj_thread_sleep(100); pjmedia_snd_port_destroy(snd_port); } if (renderer) { pjmedia_event_unsubscribe(NULL, &avi_event_cb, &avi_port, renderer); pjmedia_vid_port_destroy(renderer); } if (aud_port) pjmedia_port_destroy(aud_port); if (vid_port) pjmedia_port_destroy(vid_port); if (codec) { pjmedia_vid_codec_close(codec); pjmedia_vid_codec_mgr_dealloc_codec(NULL, codec); } return rc; }
/* API: configure the AVI */ PJ_DEF(pj_status_t) pjmedia_avi_dev_alloc( pjmedia_vid_dev_factory *f, pjmedia_avi_dev_param *p, pjmedia_vid_dev_index *p_id) { pjmedia_vid_dev_index id; struct avi_factory *cf = (struct avi_factory*)f; unsigned local_idx; struct avi_dev_info *adi = NULL; pjmedia_format avi_fmt; const pjmedia_video_format_info *vfi; pj_status_t status; PJ_ASSERT_RETURN(f && p && p_id, PJ_EINVAL); if (p_id) *p_id = PJMEDIA_VID_INVALID_DEV; /* Get a free dev */ for (local_idx=0; local_idx<cf->dev_count; ++local_idx) { if (cf->dev_info[local_idx].avi == NULL) { adi = &cf->dev_info[local_idx]; break; } } if (!adi) return PJ_ETOOMANY; /* Convert local ID to global id */ status = pjmedia_vid_dev_get_global_index(&cf->base, local_idx, &id); if (status != PJ_SUCCESS) return status; /* Reset */ if (adi->pool) { pj_pool_release(adi->pool); } pj_bzero(adi, sizeof(*adi)); /* Reinit */ PJ_ASSERT_RETURN(p->path.slen, PJ_EINVAL); adi->pool = pj_pool_create(cf->pf, "avidi%p", 512, 512, NULL); /* Open the AVI */ pj_strdup_with_null(adi->pool, &adi->fpath, &p->path); status = pjmedia_avi_player_create_streams(adi->pool, adi->fpath.ptr, 0, &adi->avi); if (status != PJ_SUCCESS) { goto on_error; } adi->vid = pjmedia_avi_streams_get_stream_by_media(adi->avi, 0, PJMEDIA_TYPE_VIDEO); if (!adi->vid) { status = PJMEDIA_EVID_BADFORMAT; PJ_LOG(4,(THIS_FILE, "Error: cannot find video in AVI %s", adi->fpath.ptr)); goto on_error; } 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, &adi->codec); if (status != PJ_SUCCESS) goto on_error; status = pjmedia_vid_codec_init(adi->codec, adi->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(adi->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; adi->enc_buf = pj_pool_alloc(adi->pool, vafp.framebytes); adi->enc_buf_size = vafp.framebytes; } /* Calculate title */ if (p->title.slen) { pj_strdup_with_null(adi->pool, &adi->title, &p->title); } else { char *start = p->path.ptr + p->path.slen; pj_str_t tmp; while (start >= p->path.ptr) { if (*start == '/' || *start == '\\') break; --start; } tmp.ptr = start + 1; tmp.slen = p->path.ptr + p->path.slen - tmp.ptr; pj_strdup_with_null(adi->pool, &adi->title, &tmp); } /* Init device info */ pj_ansi_strncpy(adi->info.name, adi->title.ptr, sizeof(adi->info.name)-1); pj_ansi_strncpy(adi->info.driver, DRIVER_NAME, sizeof(adi->info.driver)-1); adi->info.dir = PJMEDIA_DIR_CAPTURE; adi->info.has_callback = PJ_FALSE; adi->info.caps = PJMEDIA_VID_DEV_CAP_FORMAT; adi->info.fmt_cnt = 1; pjmedia_format_copy(&adi->info.fmt[0], &avi_fmt); /* Set out vars */ if (p_id) *p_id = id; p->avi_streams = adi->avi; if (p->title.slen == 0) p->title = adi->title; return PJ_SUCCESS; on_error: if (adi->codec) { pjmedia_vid_codec_close(adi->codec); adi->codec = NULL; } if (adi->pool) { pj_pool_release(adi->pool); adi->pool = NULL; } pjmedia_avi_dev_free(id); return status; }