| /* | |
| * GPAC - Multimedia Framework C SDK | |
| * | |
| * Authors: Jean Le Feuvre | |
| * Copyright (c) Telecom ParisTech 2005-2012 | |
| * All rights reserved | |
| * | |
| * This file is part of GPAC / Dummy input module | |
| * | |
| * GPAC is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU Lesser General Public License as published by | |
| * the Free Software Foundation; either version 2, or (at your option) | |
| * any later version. | |
| * | |
| * GPAC is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; see the file COPYING. If not, write to | |
| * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
| * | |
| */ | |
| #include <gpac/modules/service.h> | |
| #include <gpac/modules/codec.h> | |
| /*for GF_STREAM_PRIVATE_SCENE definition*/ | |
| #include <gpac/constants.h> | |
| #include <gpac/download.h> | |
| //#define TEST_LIBPLAYER | |
| #ifndef TEST_LIBPLAYER | |
| #ifdef WIN32 | |
| typedef u32 uint32_t; | |
| typedef u8 uint8_t; | |
| typedef s8 int8_t; | |
| typedef s32 off_t; | |
| #endif | |
| #include "player.h" | |
| #endif | |
| // variable used to detect the number of libplayer instances created - up to 2 instances | |
| static int libplayer_id = 0; | |
| //! unfortunately, saving data would not be a good solution for Mosaic Mode in ESG Application since the position changes everytime user | |
| //! uses the navigation button | |
| // value for input output windows, when save_data_instance1 equals to 1 <=> the second instance is already created with the correct size, | |
| // save these values in in_instance1 and out_instance1 so that we do not need to recalculate every time | |
| //~ static video_rect_t in_instance1, out_instance1; | |
| //~ static save_data_instance1 = 0; | |
| // variable use to detect whether a dvb instance has already started for instance 1 | |
| static int start_dvb = 0; | |
| enum | |
| { | |
| PLAYER_FILE = 0, | |
| PLAYER_DVB = 1 | |
| }; | |
| typedef struct | |
| { | |
| /*the service we're responsible for*/ | |
| GF_ClientService *service; | |
| u32 init; | |
| u32 state; | |
| u32 player_id; | |
| u32 player_type; | |
| u32 width; | |
| u32 height; | |
| char *url; | |
| #ifndef TEST_LIBPLAYER | |
| player_t *player; | |
| #endif | |
| } LibPlayerIn; | |
| static const char * LIBPLAYER_MIME_TYPES[] = { | |
| "video/x-mpeg", "mpg mpeg mp2 mpa mpe mpv2 ts", "MPEG 1/2 Movies", | |
| "video/x-mpeg-systems", "mpg mpeg mp2 mpa mpe mpv2", "MPEG 1/2 Movies", | |
| "audio/basic", "snd au", "Basic Audio", | |
| "audio/x-wav", "wav", "WAV Audio", | |
| "audio/vnd.wave", "wav", "WAV Audio", | |
| "video/x-ms-asf", "asf wma wmv asx asr", "WindowsMedia Movies", | |
| "video/x-ms-wmv", "asf wma wmv asx asr", "WindowsMedia Movies", | |
| "video/x-msvideo", "avi", "AVI Movies", | |
| "video/x-ms-video", "avi", "AVI Movies", | |
| "video/avi", "avi", "AVI Movies", | |
| "video/vnd.avi", "avi", "AVI Movies", | |
| "video/H263", "h263 263", "H263 Video", | |
| "video/H264", "h264 264", "H264 Video", | |
| "video/MPEG4", "cmp", "MPEG-4 Video", | |
| "video/mp4", "mp4", "MPEG-4 Movie", | |
| "video/quicktime", "mov qt", "QuickTime Movies", | |
| "video/webm", "webm", "Google WebM Movies", | |
| "audio/webm", "webm", "Google WebM Music", | |
| NULL | |
| }; | |
| static u32 LIBPLAYER_RegisterMimeTypes(const GF_InputService *plug) { | |
| u32 i; | |
| if (!plug) | |
| return 0; | |
| for (i = 0 ; LIBPLAYER_MIME_TYPES[i] ; i+=3) | |
| gf_service_register_mime(plug, LIBPLAYER_MIME_TYPES[i], LIBPLAYER_MIME_TYPES[i+1], LIBPLAYER_MIME_TYPES[i+2]); | |
| return i / 3; | |
| } | |
| Bool LIBPLAYER_CanHandleURL(GF_InputService *plug, const char *url) | |
| { | |
| char *sExt = strrchr(url, '.'); | |
| if (sExt) { | |
| u32 i; | |
| Bool ok = 0; | |
| char *cgi_par; | |
| // case dvb | |
| if (!strnicmp(url, "dvb://", 6)) return 1; | |
| if (!strnicmp(sExt, ".gz", 3)) sExt = strrchr(sExt, '.'); | |
| if (!strnicmp(url, "rtsp://", 7)) return 0; | |
| sExt++; | |
| cgi_par = strchr(sExt, '?'); | |
| if (cgi_par) cgi_par[0] = 0; | |
| for (i = 0 ; LIBPLAYER_MIME_TYPES[i] ; i+=3) { | |
| if (strstr(LIBPLAYER_MIME_TYPES[i+1], sExt)) { | |
| ok=1; | |
| break; | |
| } | |
| } | |
| if (cgi_par) cgi_par[0] = '?'; | |
| if (ok) return 1; | |
| } | |
| return 0; | |
| } | |
| #ifndef TEST_LIBPLAYER | |
| static int on_libplayer_event(player_event_t e, void *data) | |
| { | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerEvent] Received event %d\n", e)); | |
| switch (e) { | |
| case PLAYER_EVENT_PLAYBACK_FINISHED: | |
| player_playback_stop(data); | |
| player_playback_start(data); | |
| break; | |
| case PLAYER_EVENT_FE_HAS_LOCK: | |
| break; | |
| case PLAYER_EVENT_FE_TIMEDOUT: | |
| break; | |
| case PLAYER_EVENT_VIDEO_PICTURE: | |
| break; | |
| default: | |
| break; | |
| } | |
| return 0; | |
| } | |
| #endif | |
| GF_Err LIBPLAYER_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) | |
| { | |
| LibPlayerIn *read = (LibPlayerIn *) plug->priv; | |
| #ifndef TEST_LIBPLAYER | |
| mrl_t *mrl = NULL; | |
| #endif | |
| GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN]Â Connecting\n")); | |
| if (!read || !serv || !url) return GF_BAD_PARAM; | |
| if (!strnicmp(url, "libplayer://", 12)) url+=12; | |
| if (!read->init) { | |
| read->init=1; | |
| /* libplayer init with default width/height */ | |
| read->width = 80; | |
| read->height = 20; | |
| read->url = url; | |
| read->player_id = libplayer_id; | |
| read->player_type = PLAYER_FILE; | |
| #ifndef TEST_LIBPLAYER | |
| read->player = player_init(PLAYER_TYPE_DUMMY, PLAYER_AO_AUTO, PLAYER_VO_AUTO, PLAYER_MSG_INFO, read->player_id, on_libplayer_event); | |
| if (!read->player) { | |
| GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN]Â Failed to instanciate libplayer instance %d\n", read->player_id)); | |
| gf_service_connect_ack(serv, NULL, GF_REMOTE_SERVICE_ERROR); | |
| return GF_OK; | |
| } | |
| #endif | |
| libplayer_id++; | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] Opening URL %s for Player instance %d\n", url, read->player_id)); | |
| } | |
| #ifndef TEST_LIBPLAYER | |
| mrl = NULL; | |
| // dvb | |
| if (!strnicmp(url, "dvb://", 6)) { | |
| read->player_type = PLAYER_DVB; | |
| mrl_resource_dvb_args_t *mrl_dvb_args; | |
| mrl_dvb_args = calloc(1, sizeof(mrl_resource_dvb_args_t)); | |
| char *frequency; | |
| // fetch frequency | |
| if (frequency = strchr(url+6, '@')) { | |
| char *enc, *pid; | |
| mrl_dvb_args->frequency = atoi(frequency+1); | |
| /* | |
| * video | |
| */ | |
| // video codec | |
| if (enc = strstr(url+6, "mpeg2")) { | |
| mrl_dvb_args->video_enc = PLAYER_VIDEO_MPEG2; | |
| } | |
| else if (enc = strstr(url+6, "h264")) { | |
| mrl_dvb_args->video_enc = PLAYER_VIDEO_H264; | |
| } | |
| else { | |
| GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN]Â Unknown video encoding\n")); | |
| mrl_dvb_args->video_enc = PLAYER_VIDEO_UNKNOWN; | |
| } | |
| // video PID | |
| if (mrl_dvb_args->video_enc != PLAYER_VIDEO_UNKNOWN) { | |
| pid = strchr(enc, ':'); | |
| mrl_dvb_args->video_pid = atoi(pid+1); | |
| } | |
| /* | |
| * audio | |
| */ | |
| // audio codec | |
| if (enc = strstr(url+6, "mp2")) { | |
| mrl_dvb_args->audio_enc = PLAYER_AUDIO_MP2; | |
| } | |
| else if (enc = strstr(url+6, "ac3")) { | |
| mrl_dvb_args->audio_enc = PLAYER_AUDIO_AC3; | |
| } | |
| else { | |
| GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN]Â Unknown audio encoding\n")); | |
| mrl_dvb_args->audio_enc = PLAYER_AUDIO_UNKNOWN; | |
| } | |
| // audio PID | |
| if (mrl_dvb_args->audio_enc != PLAYER_AUDIO_UNKNOWN) { | |
| pid = strchr(enc, ':'); | |
| mrl_dvb_args->audio_pid = atoi(pid+1); | |
| } | |
| if (mrl_dvb_args->video_enc == PLAYER_VIDEO_UNKNOWN && mrl_dvb_args->audio_enc == PLAYER_AUDIO_UNKNOWN) { | |
| GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN]Â Unknown video and audio encoding\n")); | |
| free(mrl_dvb_args); | |
| return GF_BAD_PARAM; | |
| } | |
| } | |
| else { | |
| GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN]Â Unknown frequency\n")); | |
| free(mrl_dvb_args); | |
| return GF_BAD_PARAM; | |
| } | |
| // player instance 1 has not starter yet in dvb case <=> player instance 1 is not created yet | |
| if (start_dvb == 0) { | |
| mrl = mrl_new(read->player, MRL_RESOURCE_DVB, mrl_dvb_args); | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] MRL created for DVB\n")); | |
| // player has already started, zapping case, make sure the player is not recreated | |
| } else { | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] Starting DVB PES filtering\n")); | |
| player_dvb_pes_filter_start(read->player, mrl_dvb_args->video_enc, mrl_dvb_args->video_pid, mrl_dvb_args->audio_enc, mrl_dvb_args->audio_pid); | |
| } | |
| } | |
| else if (!strnicmp(url, "file://", 7) || !strstr(url, "://")) { | |
| mrl_resource_local_args_t *mrl_args; | |
| mrl_args = calloc(1, sizeof(mrl_resource_local_args_t)); | |
| if (!strnicmp(url, "file://", 7)) { | |
| mrl_args->location = strdup(url + 7); | |
| } else { | |
| mrl_args->location = strdup(url); | |
| } | |
| mrl = mrl_new (read->player, MRL_RESOURCE_FILE, mrl_args); | |
| } | |
| // only for DVB case to make sure player is only set once | |
| if (start_dvb == 0) { | |
| if (!mrl) { | |
| GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[LibPlayerIN] Failed to create MRL for url %s\n", url)); | |
| gf_service_connect_ack(serv, NULL, GF_URL_ERROR); | |
| return GF_OK; | |
| } | |
| player_mrl_set(read->player, mrl); | |
| } | |
| #endif | |
| read->state = 0; | |
| read->service = serv; | |
| /*ACK connection is OK*/ | |
| gf_service_connect_ack(serv, NULL, GF_OK); | |
| /*setup LIBPLAYER object descriptor*/ | |
| { | |
| GF_ESD *esd; | |
| GF_ObjectDescriptor *od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); | |
| od->objectDescriptorID = 1+read->player_id; | |
| esd = gf_odf_desc_esd_new(0); | |
| esd->ESID = 1+read->player_id; | |
| esd->slConfig->timestampResolution = 1000; | |
| esd->decoderConfig->streamType = GF_STREAM_PRIVATE_MEDIA; | |
| esd->decoderConfig->objectTypeIndication = GPAC_OTI_PRIVATE_MEDIA_LIBPLAYER; | |
| #ifndef TEST_LIBPLAYER | |
| esd->decoderConfig->decoderSpecificInfo->data = read; | |
| #endif | |
| gf_list_add(od->ESDescriptors, esd); | |
| gf_service_declare_media(read->service, (GF_Descriptor*)od, 0); | |
| } | |
| return GF_OK; | |
| } | |
| GF_Err LIBPLAYER_CloseService(GF_InputService *plug) | |
| { | |
| LibPlayerIn *read = (LibPlayerIn *) plug->priv; | |
| #ifndef TEST_LIBPLAYER | |
| // only disconnect if | |
| if (read->player_type == PLAYER_FILE) { | |
| player_playback_stop(read->player); | |
| fprintf(stderr, "[LibPlayerIN]player_playback_stop for instance %d\n", read->player_id); | |
| player_uninit(read->player); | |
| fprintf(stderr, "[LibPlayerIN]player_uninit for instance %d\n", read->player_id); | |
| read->player = NULL; | |
| libplayer_id--; | |
| read->state = 0; | |
| gf_service_disconnect_ack(read->service, NULL, GF_OK); | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIn] Closing libplayer instance %d\n", read->player_id)); | |
| // channel zapping dvb case, don't disconnect service | |
| } else { | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIn] Don't close service libplayer instance %d, use this instance for channel zapping\n", read->player_id)); | |
| } | |
| return GF_OK; | |
| #endif | |
| } | |
| /*Dummy input just send a file name, no multitrack to handle so we don't need to check sub_url nor expected type*/ | |
| static GF_Descriptor *LIBPLAYER_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url) | |
| { | |
| return NULL; | |
| } | |
| GF_Err LIBPLAYER_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com) | |
| { | |
| LibPlayerIn *read = (LibPlayerIn *) plug->priv; | |
| unsigned long prop = 0; | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] ServiceCommand for instance %d, read->state=%d\n", read->player_id, read->state)); | |
| if (!com->base.on_channel) return GF_NOT_SUPPORTED; | |
| if (com->command_type==GF_NET_SERVICE_HAS_AUDIO) return GF_NOT_SUPPORTED; | |
| switch (com->command_type) { | |
| case GF_NET_CHAN_SET_PULL: | |
| return GF_NOT_SUPPORTED; | |
| case GF_NET_CHAN_INTERACTIVE: | |
| return GF_OK; | |
| /*since data is file-based, no padding is needed (decoder plugin will handle it itself)*/ | |
| case GF_NET_CHAN_SET_PADDING: | |
| return GF_OK; | |
| case GF_NET_CHAN_BUFFER: | |
| return GF_OK; | |
| com->buffer.max = com->buffer.min = 0; | |
| return GF_OK; | |
| case GF_NET_CHAN_DURATION: | |
| /*this module is not made for updates, use undefined duration*/ | |
| com->duration.duration = -1; | |
| return GF_OK; | |
| case GF_NET_CHAN_PLAY: | |
| if (read->state==0) { | |
| #ifndef TEST_LIBPLAYER | |
| if ((read->player_id == 0) && (read->player_type == PLAYER_DVB) && (start_dvb == 1)) { | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] Instance %d has already started, zapping mode\n", read->player_id)); | |
| } else { | |
| player_playback_start(read->player); | |
| if ((read->player_id == 0) && (read->player_type == PLAYER_DVB)) { | |
| start_dvb = 1; | |
| } | |
| read->state = 1; | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] Starting playback for instance %d\n", read->player_id)); | |
| } | |
| #endif | |
| } | |
| return GF_OK; | |
| case GF_NET_CHAN_STOP: | |
| if (read->state==1) { | |
| #ifndef TEST_LIBPLAYER | |
| // channel zapping, don't stop channel | |
| if ((read->player_id == 0) && (read->player_type == PLAYER_DVB) && (start_dvb = 1)) { | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] Instance %d is in zapping mode, don't stop channel\n", read->player_id)); | |
| } else { | |
| player_playback_stop(read->player); | |
| read->state = 0; | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] Stopping playback for instance %d\n", read->player_id)); | |
| } | |
| #endif | |
| } | |
| return GF_OK; | |
| case GF_NET_CHAN_CONFIG: | |
| return GF_OK; | |
| case GF_NET_CHAN_GET_DSI: | |
| com->get_dsi.dsi = NULL; | |
| com->get_dsi.dsi_len = 0; | |
| return GF_OK; | |
| } | |
| return GF_OK; | |
| } | |
| GF_Err LIBPLAYER_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream) | |
| { | |
| u32 ESID; | |
| LibPlayerIn *read = (LibPlayerIn *) plug->priv; | |
| sscanf(url, "ES_ID=%ud", &ESID); | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] instance %d connect channel %d\n", read->player_id, ESID)); | |
| if (ESID != 1+read->player_id) { | |
| gf_service_connect_ack(read->service, channel, GF_STREAM_NOT_FOUND); | |
| } else { | |
| gf_service_connect_ack(read->service, channel, GF_OK); | |
| } | |
| return GF_OK; | |
| } | |
| GF_Err LIBPLAYER_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel) | |
| { | |
| LibPlayerIn *read = (LibPlayerIn *) plug->priv; | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerIN] instance %d disconnect channel\n", read->player_id)); | |
| gf_service_disconnect_ack(read->service, channel, GF_OK); | |
| return GF_OK; | |
| } | |
| Bool LIBPLAYER_CanHandleURLInService(GF_InputService *plug, const char *url) | |
| { | |
| return 0; | |
| //return 1; | |
| } | |
| static GF_Err LIBPLAYER_AttachStream(GF_BaseDecoder *dec, GF_ESD *esd) | |
| { | |
| LibPlayerIn *read; | |
| if (dec->privateStack) return GF_BAD_PARAM; | |
| if (!esd->decoderConfig->decoderSpecificInfo) return GF_BAD_PARAM; | |
| if (!esd->decoderConfig->decoderSpecificInfo->data) return GF_BAD_PARAM; | |
| read = (LibPlayerIn *) esd->decoderConfig->decoderSpecificInfo->data; | |
| if (esd->ESID!=1+read->player_id) return GF_BAD_PARAM; | |
| dec->privateStack = read; | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerDEC] AttachStream for instance %d\n", read->player_id)); | |
| esd->decoderConfig->decoderSpecificInfo->data = NULL; | |
| return GF_OK; | |
| } | |
| static GF_Err LIBPLAYER_DetachStream(GF_BaseDecoder *dec, u16 ES_ID) | |
| { | |
| LibPlayerIn *player = dec->privateStack; | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerDEC] DetachStream for instance %d\n", player ? player->player_id : -1)); | |
| dec->privateStack = NULL; | |
| return GF_OK; | |
| } | |
| static GF_Err LIBPLAYER_GetCapabilities(GF_BaseDecoder *dec, GF_CodecCapability *capability) | |
| { | |
| LibPlayerIn *read = dec->privateStack; | |
| //GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerDEC] GetCapabilities\n")); | |
| switch (capability->CapCode) { | |
| case GF_CODEC_WIDTH: | |
| capability->cap.valueInt = read->width; | |
| break; | |
| case GF_CODEC_HEIGHT: | |
| capability->cap.valueInt = read->height; | |
| break; | |
| } | |
| return GF_OK; | |
| } | |
| static GF_Err LIBPLAYER_SetCapabilities(GF_BaseDecoder *dec, GF_CodecCapability capability) | |
| { | |
| return GF_NOT_SUPPORTED; | |
| } | |
| static u32 LIBPLAYER_CanHandleStream(GF_BaseDecoder *dec, u32 StreamType, GF_ESD *esd, u8 PL) | |
| { | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerDEC] CanHandleStream\n")); | |
| if (StreamType!=GF_STREAM_PRIVATE_MEDIA) return GF_CODEC_NOT_SUPPORTED; | |
| /*don't reply to media type queries*/ | |
| if (!esd) return GF_CODEC_NOT_SUPPORTED; | |
| if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_PRIVATE_MEDIA_LIBPLAYER) return GF_CODEC_SUPPORTED; | |
| return GF_CODEC_NOT_SUPPORTED; | |
| } | |
| static const char *LIBPLAYER_GetName(GF_BaseDecoder *dec) | |
| { | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerDEC] GetName\n")); | |
| return "LibPlayer decoder"; | |
| } | |
| static GF_Err LIBPLAYER_Control(GF_PrivateMediaDecoder *dec, Bool mute, GF_Window *src, GF_Window *dst) | |
| { | |
| #ifndef TEST_LIBPLAYER | |
| video_rect_t in, out; | |
| LibPlayerIn *read = dec->privateStack; | |
| u32 width, height; | |
| if (!read) return GF_OK; | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerDEC] Control instance %d\n",read->player_id)); | |
| //! unfortunately, saving data would not be a good solution for Mosaic Mode in ESG Application since the position changes everytime user | |
| //! uses the navigation button | |
| //~ if (read->player_id == 1 && save_data_instance1 == 1) { | |
| //~ fprintf(stderr, "in here for save data instance\n"); | |
| //~ player_video_io_windows_set(read->player, &in_instance1, &out_instance1); | |
| //~ | |
| //~ return GF_OK; | |
| //~ | |
| //~ } else { | |
| width = mrl_get_property(read->player, NULL, MRL_PROPERTY_VIDEO_WIDTH); | |
| height = mrl_get_property(read->player, NULL, MRL_PROPERTY_VIDEO_HEIGHT); | |
| //~ } | |
| if((width != read->width) || (height != read->height)) { | |
| fprintf(stderr, "in here for video size changed\t"); | |
| fprintf(stderr, "width %d read->width %d height %d read->height %d\n", width, read->width, height, read->height); | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerDEC] video size changed to width %d - height %d\n", width, height)); | |
| if (width && height) { | |
| read->width = width; | |
| read->height = height; | |
| } | |
| return GF_BUFFER_TOO_SMALL; | |
| } | |
| in.x = src->x; | |
| in.y = src->y; | |
| in.w = src->w; | |
| in.h = src->h; | |
| out.x = dst->x; | |
| out.y = dst->y; | |
| out.w = dst->w; | |
| out.h = dst->h; | |
| player_video_io_windows_set(read->player, &in, &out); | |
| //! unfortunately, saving data would not be a good solution for Mosaic Mode in ESG Application since the position changes everytime user | |
| //! uses the navigation button | |
| //~ if (read->player_id == 1) { | |
| //~ in_instance1 = in; | |
| //~ // //~ out_instance1.w = out.w; | |
| //~ // //~ out_instance1.h = out.h; | |
| //~ out_instance1 = out; | |
| //~ save_data_instance1 = 1; | |
| //~ } | |
| //~ | |
| #endif | |
| GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerDEC] Repositioning video src %d %d %d %d - dest %d %d %d %d\n", src->x, src->y, src->w, src->h, dst->x, dst->y, dst->w, dst->h) ); | |
| return GF_OK; | |
| } | |
| GPAC_MODULE_EXPORT | |
| const u32 *QueryInterfaces() | |
| { | |
| static u32 si [] = { | |
| GF_NET_CLIENT_INTERFACE, | |
| GF_PRIVATE_MEDIA_DECODER_INTERFACE, | |
| 0 | |
| }; | |
| return si; | |
| } | |
| GPAC_MODULE_EXPORT | |
| GF_BaseInterface *LoadInterface(u32 InterfaceType) | |
| { | |
| if (InterfaceType == GF_NET_CLIENT_INTERFACE) { | |
| LibPlayerIn *read; | |
| GF_InputService *plug; | |
| GF_SAFEALLOC(plug, GF_InputService); | |
| memset(plug, 0, sizeof(GF_InputService)); | |
| GF_REGISTER_MODULE_INTERFACE(plug, GF_NET_CLIENT_INTERFACE, "LibPlayer Input", "gpac distribution") | |
| plug->RegisterMimeTypes = LIBPLAYER_RegisterMimeTypes; | |
| plug->CanHandleURL = LIBPLAYER_CanHandleURL; | |
| plug->ConnectService = LIBPLAYER_ConnectService; | |
| plug->CloseService = LIBPLAYER_CloseService; | |
| plug->GetServiceDescriptor = LIBPLAYER_GetServiceDesc; | |
| plug->ConnectChannel = LIBPLAYER_ConnectChannel; | |
| plug->DisconnectChannel = LIBPLAYER_DisconnectChannel; | |
| plug->ServiceCommand = LIBPLAYER_ServiceCommand; | |
| plug->CanHandleURLInService = LIBPLAYER_CanHandleURLInService; | |
| GF_SAFEALLOC(read, LibPlayerIn); | |
| plug->priv = read; | |
| return (GF_BaseInterface *)plug; | |
| } else if (InterfaceType == GF_PRIVATE_MEDIA_DECODER_INTERFACE) { | |
| GF_PrivateMediaDecoder *ifce; | |
| GF_SAFEALLOC(ifce, GF_PrivateMediaDecoder); | |
| GF_REGISTER_MODULE_INTERFACE(ifce, GF_PRIVATE_MEDIA_DECODER_INTERFACE, "LibPlayer Decoder", "gpac distribution") | |
| /*setup our own interface*/ | |
| ifce->AttachStream = LIBPLAYER_AttachStream; | |
| ifce->DetachStream = LIBPLAYER_DetachStream; | |
| ifce->GetCapabilities = LIBPLAYER_GetCapabilities; | |
| ifce->SetCapabilities = LIBPLAYER_SetCapabilities; | |
| ifce->Control = LIBPLAYER_Control; | |
| ifce->CanHandleStream = LIBPLAYER_CanHandleStream; | |
| ifce->GetName = LIBPLAYER_GetName; | |
| return (GF_BaseInterface *) ifce; | |
| } | |
| return NULL; | |
| } | |
| GPAC_MODULE_EXPORT | |
| void ShutdownInterface(GF_BaseInterface *bi) | |
| { | |
| if (bi->InterfaceType==GF_NET_CLIENT_INTERFACE) { | |
| GF_InputService *ifcn = (GF_InputService*)bi; | |
| LibPlayerIn *read = (LibPlayerIn*)ifcn->priv; | |
| gf_free(read); | |
| gf_free(bi); | |
| } else if (bi->InterfaceType == GF_PRIVATE_MEDIA_DECODER_INTERFACE) { | |
| gf_free(bi); | |
| } | |
| } | |
| GPAC_MODULE_STATIC_DECLARATION( libplayer ) |