static int handle_metadata0(rtmp_t *r, AMFObject *obj, media_pipe_t *mp, char *errstr, size_t errlen) { AVal metastring; AMFObjectProperty prop; prop_t *m = mp->mp_prop_metadata; AMFProp_GetString(AMF_GetProp(obj, NULL, 0), &metastring); if(!AVMATCH(&metastring, &av_onMetaData)) { snprintf(errstr, errlen, "No metadata in metadata packet"); return -1; } if(RTMP_FindFirstMatchingProperty(obj, &av_duration, &prop) && prop.p_type == AMF_NUMBER && prop.p_vu.p_number > 0) { prop_set_float(prop_create(m, "duration"), prop.p_vu.p_number); r->total_duration = prop.p_vu.p_number * 1000; mp_set_duration(mp, r->total_duration * 1000LL); mp_set_clr_flags(mp, MP_CAN_SEEK, 0); if(r->ss == NULL && !(r->va->flags & BACKEND_VIDEO_NO_SUBTITLE_SCAN)) r->ss = sub_scanner_create(r->url, mp->mp_prop_subtitle_tracks, r->va, 0); } else { r->total_duration = 0; mp_set_duration(mp, AV_NOPTS_VALUE); mp_set_clr_flags(mp, 0, MP_CAN_SEEK); } if((RTMP_FindFirstMatchingProperty(obj, &av_videoframerate, &prop) && RTMP_FindFirstMatchingProperty(obj, &av_framerate, &prop)) && prop.p_type == AMF_NUMBER) { r->vframeduration = 1000000.0 / prop.p_vu.p_number; mp->mp_framerate.num = 1000000; mp->mp_framerate.den = prop.p_vu.p_number; } r->width = r->height = 0; if(RTMP_FindFirstMatchingProperty(obj, &av_width, &prop) && prop.p_type == AMF_NUMBER) r->width = prop.p_vu.p_number; if(RTMP_FindFirstMatchingProperty(obj, &av_height, &prop) && prop.p_type == AMF_NUMBER) r->height = prop.p_vu.p_number; if(r->width && r->height) TRACE(TRACE_DEBUG, "RTMP", "Video size %d x %d", r->width, r->height); return 0; }
void mp_configure(media_pipe_t *mp, int flags, int buffer_size, int64_t duration, const char *type) { hts_mutex_lock(&mp->mp_mutex); prop_set_string(mp->mp_prop_playstatus, "play"); mp->mp_framerate.num = 0; mp->mp_framerate.den = 1; mp->mp_max_realtime_delay = INT32_MAX; mp_set_clr_flags_locked(mp, flags, MP_PRE_BUFFERING | MP_FLUSH_ON_HOLD | MP_ALWAYS_SATISFIED | MP_CAN_SEEK | MP_CAN_PAUSE | MP_CAN_EJECT); prop_set(mp->mp_prop_root, "type", PROP_SET_STRING, type); switch(buffer_size) { case MP_BUFFER_NONE: mp->mp_buffer_limit = 0; break; case MP_BUFFER_SHALLOW: mp->mp_buffer_limit = 1 * 1024 * 1024; break; case MP_BUFFER_DEEP: mp->mp_buffer_limit = video_settings.video_buffer_size * 1024 * 1024; break; } prop_set_int(mp->mp_prop_buffer_limit, mp->mp_buffer_limit); mp_set_duration(mp, duration); if(mp->mp_clock_setup != NULL) mp->mp_clock_setup(mp, mp->mp_audio.mq_stream != -1); if(mp->mp_flags & MP_PRE_BUFFERING) mp_check_underrun(mp); hts_mutex_unlock(&mp->mp_mutex); }
event_t * fa_xmp_playfile(media_pipe_t *mp, FILE *f, char *errbuf, size_t errlen, int hold, const char *url, size_t size) { event_t *e = NULL; xmp_context ctx = xmp_create_context(); // struct xmp_module_info mi; struct xmp_frame_info fi; char *u = mystrdupa(url); mp->mp_audio.mq_stream = 0; mp_configure(mp, MP_CAN_PAUSE | MP_CAN_SEEK, MP_BUFFER_SHALLOW, 0, "tracks"); mp_become_primary(mp); if(xmp_load_modulef(ctx, f, u, size) >= 0) { if(xmp_start_player(ctx, 44100, 0) == 0) { media_buf_t *mb = NULL; media_queue_t *mq = &mp->mp_audio; while(1) { if(mb == NULL) { if(xmp_play_frame(ctx)) { e = event_create_type(EVENT_EOF); break; } xmp_get_frame_info(ctx, &fi); if(fi.loop_count > 0) { e = event_create_type(EVENT_EOF); break; } mb = media_buf_alloc_unlocked(mp, fi.buffer_size); mb->mb_data_type = MB_AUDIO; mb->mb_channels = 2; mb->mb_rate = 44100; mb->mb_pts = fi.time * 1000; mb->mb_drive_clock = 1; memcpy(mb->mb_data, fi.buffer, fi.buffer_size); mp_set_duration(mp, fi.total_time * 1000); } if((e = mb_enqueue_with_events(mp, mq, mb)) == NULL) { mb = NULL; /* Enqueue succeeded */ continue; } if(event_is_type(e, EVENT_PLAYQUEUE_JUMP)) { mp_flush(mp, 0); break; } else if(event_is_action(e, ACTION_SKIP_BACKWARD) || event_is_action(e, ACTION_SKIP_FORWARD) || event_is_action(e, ACTION_STOP)) { mp_flush(mp, 0); break; } event_release(e); } xmp_end_player(ctx); } else { snprintf(errbuf, errlen, "XMP failed to start"); } } else { snprintf(errbuf, errlen, "XMP Loading error"); } // prop_ref_dec(dur); xmp_free_context(ctx); return e; }