void media_input::select_audio_stream(int audio_stream) { if (_have_active_video_read) { (void)finish_video_frame_read(); } if (_have_active_audio_read) { (void)finish_audio_blob_read(); } if (_have_active_subtitle_read) { (void)finish_subtitle_box_read(); } assert(audio_stream >= 0); assert(audio_stream < audio_streams()); _active_audio_stream = audio_stream; int o, s; get_audio_stream(_active_audio_stream, o, s); for (size_t i = 0; i < _media_objects.size(); i++) { for (int j = 0; j < _media_objects[i].audio_streams(); j++) { _media_objects[i].audio_stream_set_active(j, (i == static_cast<size_t>(o) && j == s)); } } // Re-set audio blob template _audio_blob = _media_objects[o].audio_blob_template(s); }
void media_input::get_audio_stream(int stream, int &media_object, int &media_object_audio_stream) const { assert(stream < audio_streams()); size_t i = 0; while (_media_objects[i].audio_streams() < stream + 1) { stream -= _media_objects[i].audio_streams(); i++; } media_object = i; media_object_audio_stream = stream; }
void media_input::get_audio_stream(int stream, int &media_object, int &media_object_audio_stream) const { assert(stream < audio_streams()); for (size_t i = 0; i < _media_objects.size(); i++) { if (_media_objects[i].audio_streams() < stream + 1) { stream -= _media_objects[i].audio_streams(); continue; } media_object = i; media_object_audio_stream = stream; break; } }
void media_input::open(const std::vector<std::string> &urls, const device_request &dev_request) { assert(urls.size() > 0); // Open media objects _is_device = dev_request.is_device(); _media_objects.resize(urls.size()); for (size_t i = 0; i < urls.size(); i++) { _media_objects[i].open(urls[i], dev_request); } // Construct id for this input _id = basename(_media_objects[0].url()); for (size_t i = 1; i < _media_objects.size(); i++) { _id += '/'; _id += basename(_media_objects[i].url()); } // Gather metadata for (size_t i = 0; i < _media_objects.size(); i++) { // Note that we may have multiple identical tag names in our metadata for (size_t j = 0; j < _media_objects[i].tags(); j++) { _tag_names.push_back(_media_objects[i].tag_name(j)); _tag_values.push_back(_media_objects[i].tag_value(j)); } } // Gather streams and stream names for (size_t i = 0; i < _media_objects.size(); i++) { for (int j = 0; j < _media_objects[i].video_streams(); j++) { _video_stream_names.push_back(_media_objects[i].video_frame_template(j).format_info()); } } if (_video_stream_names.size() > 1) { for (size_t i = 0; i < _video_stream_names.size(); i++) { _video_stream_names[i].insert(0, std::string(1, '#') + str::from(i + 1) + '/' + str::from(_video_stream_names.size()) + ": "); } } for (size_t i = 0; i < _media_objects.size(); i++) { for (int j = 0; j < _media_objects[i].audio_streams(); j++) { _audio_stream_names.push_back(_media_objects[i].audio_blob_template(j).format_info()); } } if (_audio_stream_names.size() > 1) { for (size_t i = 0; i < _audio_stream_names.size(); i++) { _audio_stream_names[i].insert(0, std::string(1, '#') + str::from(i + 1) + '/' + str::from(_audio_stream_names.size()) + ": "); } } for (size_t i = 0; i < _media_objects.size(); i++) { for (int j = 0; j < _media_objects[i].subtitle_streams(); j++) { _subtitle_stream_names.push_back(_media_objects[i].subtitle_box_template(j).format_info()); } } if (_subtitle_stream_names.size() > 1) { for (size_t i = 0; i < _subtitle_stream_names.size(); i++) { _subtitle_stream_names[i].insert(0, std::string(1, '#') + str::from(i + 1) + '/' + str::from(_subtitle_stream_names.size()) + ": "); } } // Set duration information _duration = std::numeric_limits<int64_t>::max(); for (size_t i = 0; i < _media_objects.size(); i++) { for (int j = 0; j < _media_objects[i].video_streams(); j++) { int64_t d = _media_objects[i].video_duration(j); if (d < _duration) { _duration = d; } } for (int j = 0; j < _media_objects[i].audio_streams(); j++) { int64_t d = _media_objects[i].audio_duration(j); if (d < _duration) { _duration = d; } } // Ignore subtitle stream duration; it seems unreliable and is not important anyway. } // Skip advertisement in 3dtv.at movies. Only works for single media objects. try { _initial_skip = str::to<int64_t>(tag_value("StereoscopicSkip")); } catch (...) { } // Find stereo layout and set active video stream(s) _supports_stereo_layout_separate = false; if (video_streams() == 2) { int o0, o1, v0, v1; get_video_stream(0, o0, v0); get_video_stream(1, o1, v1); video_frame t0 = _media_objects[o0].video_frame_template(v0); video_frame t1 = _media_objects[o1].video_frame_template(v1); if (t0.width == t1.width && t0.height == t1.height && (t0.aspect_ratio <= t1.aspect_ratio && t0.aspect_ratio >= t1.aspect_ratio) && t0.layout == t1.layout && t0.color_space == t1.color_space && t0.value_range == t1.value_range && t0.chroma_location == t1.chroma_location) { _supports_stereo_layout_separate = true; } } if (_supports_stereo_layout_separate) { _active_video_stream = 0; int o, s; get_video_stream(_active_video_stream, o, s); _video_frame = _media_objects[o].video_frame_template(s); _video_frame.stereo_layout = parameters::layout_separate; } else if (video_streams() > 0) { _active_video_stream = 0; int o, s; get_video_stream(_active_video_stream, o, s); _video_frame = _media_objects[o].video_frame_template(s); } else { _active_video_stream = -1; } if (_active_video_stream >= 0) { select_video_stream(_active_video_stream); } // Set active audio stream _active_audio_stream = (audio_streams() > 0 ? 0 : -1); if (_active_audio_stream >= 0) { int o, s; get_audio_stream(_active_audio_stream, o, s); _audio_blob = _media_objects[o].audio_blob_template(s); select_audio_stream(_active_audio_stream); } // Set active subtitle stream _active_subtitle_stream = -1; // no subtitles by default // Print summary msg::inf(_("Input:")); for (int i = 0; i < video_streams(); i++) { int o, s; get_video_stream(i, o, s); msg::inf(4, _("Video %s: %s"), video_stream_name(i).c_str(), _media_objects[o].video_frame_template(s).format_name().c_str()); } if (video_streams() == 0) { msg::inf(4, _("No video.")); } for (int i = 0; i < audio_streams(); i++) { int o, s; get_audio_stream(i, o, s); msg::inf(4, _("Audio %s: %s"), audio_stream_name(i).c_str(), _media_objects[o].audio_blob_template(s).format_name().c_str()); } if (audio_streams() == 0) { msg::inf(4, _("No audio.")); } for (int i = 0; i < subtitle_streams(); i++) { int o, s; get_subtitle_stream(i, o, s); msg::inf(4, _("Subtitle %s: %s"), subtitle_stream_name(i).c_str(), _media_objects[o].subtitle_box_template(s).format_name().c_str()); } if (subtitle_streams() == 0) { msg::inf(4, _("No subtitle.")); } msg::inf(4, _("Duration: %g seconds"), duration() / 1e6f); if (video_streams() > 0) { msg::inf(4, _("Stereo layout: %s"), parameters::stereo_layout_to_string( video_frame_template().stereo_layout, video_frame_template().stereo_layout_swap).c_str()); } }
void media_input::open(const std::vector<std::string> &urls) { assert(urls.size() > 0); // Open media objects _media_objects.resize(urls.size()); for (size_t i = 0; i < urls.size(); i++) { _media_objects[i].open(urls[i]); } // Construct id for this input _id = basename(_media_objects[0].url()); for (size_t i = 1; i < _media_objects.size(); i++) { _id += '/'; _id += basename(_media_objects[i].url()); } // Gather metadata for (size_t i = 0; i < _media_objects.size(); i++) { std::string pfx = (_media_objects.size() == 1 ? "" : str::from(i + 1) + " - "); for (size_t j = 0; j < _media_objects[i].tags(); j++) { _tag_names.push_back(pfx + _media_objects[i].tag_name(j)); _tag_values.push_back(pfx + _media_objects[i].tag_value(j)); } } // Gather streams and stream names for (size_t i = 0; i < _media_objects.size(); i++) { std::string pfx = (_media_objects.size() == 1 ? "" : str::from(i + 1) + " - "); for (int j = 0; j < _media_objects[i].video_streams(); j++) { std::string pfx2 = (_media_objects[i].video_streams() == 1 ? "" : str::from(j + 1) + " - "); _video_stream_names.push_back(pfx + pfx2 + _media_objects[i].video_frame_template(j).format_info()); } } for (size_t i = 0; i < _media_objects.size(); i++) { std::string pfx = (_media_objects.size() == 1 ? "" : str::from(i + 1) + " - "); for (int j = 0; j < _media_objects[i].audio_streams(); j++) { std::string pfx2 = (_media_objects[i].audio_streams() == 1 ? "" : str::from(j + 1) + " - "); _audio_stream_names.push_back(pfx + pfx2 + _media_objects[i].audio_blob_template(j).format_info()); } } for (size_t i = 0; i < _media_objects.size(); i++) { std::string pfx = (_media_objects.size() == 1 ? "" : str::from(i + 1) + " - "); for (int j = 0; j < _media_objects[i].subtitle_streams(); j++) { std::string pfx2 = (_media_objects[i].subtitle_streams() == 1 ? "" : str::from(j + 1) + " - "); _subtitle_stream_names.push_back(pfx + pfx2 + _media_objects[i].subtitle_box_template(j).format_info()); } } // Set duration information _duration = std::numeric_limits<int64_t>::max(); for (size_t i = 0; i < _media_objects.size(); i++) { for (int j = 0; j < _media_objects[i].video_streams(); j++) { int64_t d = _media_objects[i].video_duration(j); if (d < _duration) { _duration = d; } } for (int j = 0; j < _media_objects[i].audio_streams(); j++) { int64_t d = _media_objects[i].audio_duration(j); if (d < _duration) { _duration = d; } } for (int j = 0; j < _media_objects[i].subtitle_streams(); j++) { // int64_t d = _media_objects[i].subtitle_duration(j); // if (d < _duration) // { // _duration = d; // } } } // Skip advertisement in 3dtv.at movies. Only works for single media objects. try { _initial_skip = str::to<int64_t>(tag_value("StereoscopicSkip")); } catch (...) { } // Find stereo layout and set active video stream(s) _supports_stereo_layout_separate = false; if (video_streams() == 2) { int o0, o1, v0, v1; get_video_stream(0, o0, v0); get_video_stream(1, o1, v1); video_frame t0 = _media_objects[o0].video_frame_template(v0); video_frame t1 = _media_objects[o1].video_frame_template(v1); if (t0.width == t1.width && t0.height == t1.height && (t0.aspect_ratio <= t1.aspect_ratio && t0.aspect_ratio >= t1.aspect_ratio) && t0.layout == t1.layout && t0.color_space == t1.color_space && t0.value_range == t1.value_range && t0.chroma_location == t1.chroma_location) { _supports_stereo_layout_separate = true; } } if (_supports_stereo_layout_separate) { _active_video_stream = 0; int o, s; get_video_stream(_active_video_stream, o, s); _video_frame = _media_objects[o].video_frame_template(s); _video_frame.stereo_layout = video_frame::separate; } else if (video_streams() > 0) { _active_video_stream = 0; int o, s; get_video_stream(_active_video_stream, o, s); _video_frame = _media_objects[o].video_frame_template(s); } else { _active_video_stream = -1; } if (_active_video_stream >= 0) { select_video_stream(_active_video_stream); } // Set active audio stream _active_audio_stream = (audio_streams() > 0 ? 0 : -1); if (_active_audio_stream >= 0) { int o, s; get_audio_stream(_active_audio_stream, o, s); _audio_blob = _media_objects[o].audio_blob_template(s); select_audio_stream(_active_audio_stream); } // Set active subtitle stream _active_subtitle_stream = -1; // no subtitles by default // Print summary msg::inf("Input:"); for (int i = 0; i < video_streams(); i++) { int o, s; get_video_stream(i, o, s); msg::inf(" Video %s: %s", video_stream_name(i).c_str(), _media_objects[o].video_frame_template(s).format_name().c_str()); } if (video_streams() == 0) { msg::inf(" No video."); } for (int i = 0; i < audio_streams(); i++) { int o, s; get_audio_stream(i, o, s); msg::inf(" Audio %s: %s", audio_stream_name(i).c_str(), _media_objects[o].audio_blob_template(s).format_name().c_str()); } if (audio_streams() == 0) { msg::inf(" No audio."); } for (int i = 0; i < subtitle_streams(); i++) { int o, s; get_subtitle_stream(i, o, s); msg::inf(" Subtitle %s: %s", subtitle_stream_name(i).c_str(), _media_objects[o].subtitle_box_template(s).format_name().c_str()); } if (subtitle_streams() == 0) { msg::inf(" No subtitles."); } msg::inf(" Duration: %g seconds", duration() / 1e6f); if (video_streams() > 0) { msg::inf(" Stereo layout: %s", video_frame::stereo_layout_to_string( video_frame_template().stereo_layout, video_frame_template().stereo_layout_swap).c_str()); } }