Projects
Multimedia
bento4
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 21
View file
bento4.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Sat Jul 24 19:37:09 UTC 2021 - Luigi Baldoni <aloisio@gmx.com> + +- Update to version 1.6.0-639 + +------------------------------------------------------------------- Sun Jun 13 05:55:12 UTC 2021 - Luigi Baldoni <aloisio@gmx.com> - Update to version 1.6.0-638
View file
bento4.spec
Changed
@@ -16,10 +16,10 @@ # -%define _over 1.6.0-638 -%define _libver 1_6_0r638 +%define _over 1.6.0-639 +%define _libver 1_6_0r639 Name: bento4 -Version: 1.6.0r638 +Version: 1.6.0r639 Release: 0 Summary: C++ toolkit for all your MP4 and MPEG DASH media format needs License: GPL-2.0-or-later
View file
bento4-1.6.0r638.tar.gz/Build/Docker/Dockerfile -> bento4-1.6.0r639.tar.gz/Build/Docker/Dockerfile
Changed
@@ -1,7 +1,7 @@ FROM alpine:latest # Setup environment variables -ENV BENTO4_VERSION 1.6.0-638 +ENV BENTO4_VERSION 1.6.0-639 # Install Dependencies RUN apk update && apk add --no-cache ca-certificates bash python3 make cmake gcc g++ git
View file
bento4-1.6.0r638.tar.gz/Documents/MkDocs/src/developers/dash/multi_bitrate_audio.md -> bento4-1.6.0r639.tar.gz/Documents/MkDocs/src/developers/dash/multi_bitrate_audio.md
Changed
@@ -1,11 +1,14 @@ MULTI-BITRATE AUDIO =================== -The most common use of MPEG DASH is for delivering adaptive streaming presentations to players. The adaptive part is achieved by offering the same video streams encoded at different bitrates (and typically different resolutions). When properly encoded, the segments of media for the different video bitrates are such that seamless transition from one bitrate set to another can be done on-the-fly without glitches. +The most common use of MPEG DASH is for delivering adaptive streaming presentations to players. The adaptive part is achieved by offering the same video stream encoded at different bitrates (and typically different resolutions). When properly encoded, the segments of media for the different video bitrates are such that seamless transition from one bitrate set to another can be done on the fly without glitches. -For audio, however, it is typical to only have one bitrate. Offering multiple audio variants is often limited to offering a choice of stereo and multi-channel audio, where the stereo stream is usually encoded with AAC, and the multi-channel stream(s) with Dolby Digital or similar. The main reason for only having a single bitrate is the fact that with AAC and other codecs, seamless transition between audio streams encoded at different bitrates isn't easy or even possible. A second reason is that the audio bitrate is usually much lower than the video bitrate, so varrying the audio bitrate doesn't offer much of a difference in terms of the absolute total bitrate that the player has to receive. +For audio, however, it is typical to only have one bitrate. Offering multiple audio variants is often limited to offering a choice of stereo and multi-channel audio, where the stereo stream is usually encoded with AAC, and the multi-channel stream(s) with Dolby Digital or similar. The main reason for only having a single bitrate is the fact that with AAC and other codecs, seamless transition between audio streams encoded at different bitrates isn't easy or often not even possible. A second reason is that the audio bitrate is usually much lower than the video bitrate, so varrying the audio bitrate doesn't offer much of a difference in terms of the absolute total bitrate that the player has to receive. -With new generations of codecs, like xHE-AAC ("Extended High Efficiency AAC"), which combines the MPEG-D USAC standard (ISO/IEC 23003-3)) and appropriate parts of the MPEG-D DRC Loudness Control Profile or Dynamic Range Control Profile, it is now possible to offer audio encoded at different bitrates, and allow the player to seamlessly switch between the different bitrates on the fly. +With new generations of codecs, like xHE-AAC, which combines the "Extended High Efficiency AAC" profile of the MPEG-D USAC standard (ISO/IEC 23003-3) and appropriate parts of the MPEG-D DRC Loudness Control Profile or Dynamic Range Control Profile, it is now possible to offer audio encoded at different bitrates, and allow the player to seamlessly switch between the different bitrates on the fly + + +To learn more about the xHE-AAC audio codec, please visit Fraunhofer's [www.xhe-aac.com](https://www.xhe-aac.com) website The `mp4dash` tool supports input audio files that are encoded with xHE-AAC. @@ -20,10 +23,10 @@ # xHE-AAC with HLS -With HLS, more precise control may be needed. With HLS, every possible combination of audio and video streams must be listed explicitly in the playlist (as opposed to MPEG DASH, where the audio and video streams are listed separately in the manifest, and it is up to the player to pick the right combination of audio and video streams). +With HLS, more precise control may be needed. With HLS, every possible combination of audio and video streams must be listed explicitly in the playlist (as opposed to an MPEG DASH manifest, where the audio and video streams are listed separately in the manifest, and it is up to the player to pick the right combination of audio and video streams). By default, the `mp4dash` packager, when creating the HLS playlist, will list all possible combinations of audio and video streams. This means that if you have N audio streams and M video streams, the HLS playlist will have N*M `#EXT-X-STREAM-INF` entries, one for each possible (audio,video) pair. -If you need more control over the different combinations listed in the playlist, you can use the `hls_group` and `hls_group_match` input specifiers. The `hls_group` specifier for audio input files assigns a group name to the audio track. The `hls_group_match` specifier for video input files specifies which should be combined with that video track If `hls_group_match` is not set, or set to `*`, all audio groups will be combined with the video track. +If you need more control over the different combinations listed in the playlist, you can use the `hls_group` and `hls_group_match` input specifiers. The `hls_group` specifier for audio input files assigns a group name to the audio track. The `hls_group_match` specifier for video input files specifies which should be combined with that video track If `hls_group_match` is not set, or set to `*`, all audio groups will be combined with the video track. For an explicit list of audio groups that should be combined with a video stream, the `hls_group_match` specifier can be set to a list of group names, separated by `&`. !!! example "Example: audio-only, 4 bitrates" ``` @@ -42,10 +45,17 @@ ``` The playlist will have 12 `#EXT-X-STREAM-INF` entries -!!! example "Example: 4 audio bitrates, 3 video bitrates, with only the lowest bitrate video combined with multiple audio bitrates" +!!! example "Example: 4 audio bitrates, 3 video bitrates, with only the lowest bitrate video combined with all audio bitrates" ``` - mp4dash --hls [+hls_group=audio_16]audio-16kbps.mp4 [+hls_group=audio_32]audio-32kbps.mp4 [+hls_group=audio_64]audio-64kbps.mp4 [+hls_group=audio_128]audio-128kbps.mp4 "[+hls_group_match=audio_16&audio_32&audio_64&audio_128]video_00500.mp4" video_00800.mp4 video_01400.mp4 + mp4dash --hls [+hls_group=audio_16]audio-16kbps.mp4 [+hls_group=audio_32]audio-32kbps.mp4 [+hls_group=audio_64]audio-64kbps.mp4 [+hls_group=audio_128]audio-128kbps.mp4 "[+hls_group_match=*]video_00500.mp4" "[+hls_group_match=audio128]video_00800.mp4" "[+hls_group_match=audio128]video_01400.mp4" ``` - The playlist will have 4 `#EXT-X-STREAM-INF` entries + The playlist will have 6 `#EXT-X-STREAM-INF` entries (4 with the first video bitrate, and one with each of the other two) + + +!!! example "Example: 4 audio bitrates, 3 video bitrates, with only the lowest bitrate video combined with 3 audio bitrates" + ``` + mp4dash --hls [+hls_group=audio_16]audio-16kbps.mp4 [+hls_group=audio_32]audio-32kbps.mp4 [+hls_group=audio_64]audio-64kbps.mp4 [+hls_group=audio_128]audio-128kbps.mp4 "[+hls_group_match=audio_16&audio_32&audio_64&audio_64]video_00500.mp4" "[+hls_group_match=audio128]video_00800.mp4" "[+hls_group_match=audio128]video_01400.mp4" + ``` + The playlist will have 5 `#EXT-X-STREAM-INF` entries (3 with the first video bitrate, and one with each of the other two)
View file
bento4-1.6.0r638.tar.gz/Documents/MkDocs/src/developers/index.md -> bento4-1.6.0r639.tar.gz/Documents/MkDocs/src/developers/index.md
Changed
@@ -18,7 +18,7 @@ Source Code ----------- -The code is hosted on GitHub: https://github.com/axiomatic-systems/Bento4 You can browse the source code directly through the GitHub interface, or download a copy of the source tree using the GitHub download link or a git client from the command line: +The code is hosted on GitHub: [https://github.com/axiomatic-systems/Bento4](https://github.com/axiomatic-systems/Bento4) You can browse the source code directly through the GitHub interface, or download a copy of the source tree using the GitHub download link or a git client from the command line: ``` git clone https://github.com/axiomatic-systems/Bento4.git
View file
bento4-1.6.0r638.tar.gz/Documents/MkDocs/src/index.md -> bento4-1.6.0r639.tar.gz/Documents/MkDocs/src/index.md
Changed
@@ -1,8 +1,8 @@ Welcome to Bento4 ====================== -Bento4 MP4, DASH/HLS/CMAF Class Library, SDK and Tools ------------------------------------------------------- +Bento4 MP4, DASH, HLS, CMAF SDK and Tools +----------------------------------------- A fast, modern, open source C++ toolkit for all your MP4 and DASH/HLS/CMAF media format needs.
View file
bento4-1.6.0r638.tar.gz/Source/C++/Apps/Mp4Fragment/Mp4Fragment.cpp -> bento4-1.6.0r639.tar.gz/Source/C++/Apps/Mp4Fragment/Mp4Fragment.cpp
Changed
@@ -615,9 +615,18 @@ // index of the first sample in the group, which may not be correct. This // should be fixed later) unsigned int sample_desc_index = cursor->m_Sample.GetDescriptionIndex(); - unsigned int tfhd_flags = AP4_TFHD_FLAG_DEFAULT_BASE_IS_MOOF | AP4_TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX_PRESENT; - if (cursor->m_Track->GetType() == AP4_Track::TYPE_VIDEO) { - tfhd_flags |= AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT; + + // set initial flag values + AP4_UI32 tfhd_flags = AP4_TFHD_FLAG_DEFAULT_BASE_IS_MOOF | AP4_TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX_PRESENT; + AP4_UI32 trun_flags = AP4_TRUN_FLAG_DATA_OFFSET_PRESENT | + AP4_TRUN_FLAG_SAMPLE_SIZE_PRESENT; + AP4_UI32 sync_sample_flags = 0; + AP4_UI32 non_sync_sample_flags = 0x10000; // 0x10000 -> sample_is_non_sync + if (cursor->m_Track->GetType() == AP4_Track::TYPE_VIDEO || + (cursor->m_Track->GetSampleDescriptionCount() > 0 && + cursor->m_Track->GetSampleDescription(0)->GetFormat() == AP4_SAMPLE_FORMAT_AC_4)) { + non_sync_sample_flags |= 0x1000000; // sample_depends_on=1 (not I frame) + sync_sample_flags |= 0x2000000; // sample_depends_on=2 (I frame) } // setup the moof structure @@ -632,31 +641,19 @@ 0, 0, 0); - if (tfhd_flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT) { - tfhd->SetDefaultSampleFlags(0x1010000); // sample_is_non_sync_sample=1, sample_depends_on=1 (not I frame) - } - traf->AddChild(tfhd); if (!Options.no_tfdt) { AP4_TfdtAtom* tfdt = new AP4_TfdtAtom(1, cursor->m_Timestamp + (AP4_UI64)(Options.tfdt_start * (double)cursor->m_Track->GetMediaTimeScale())); traf->AddChild(tfdt); } - AP4_UI32 trun_flags = AP4_TRUN_FLAG_DATA_OFFSET_PRESENT | - AP4_TRUN_FLAG_SAMPLE_SIZE_PRESENT; - AP4_UI32 first_sample_flags = 0; - if ( (cursor->m_Track->GetType() == AP4_Track::TYPE_VIDEO) || - (cursor->m_Track->GetSampleDescriptionCount() >= 1 && cursor->m_Track->GetSampleDescription(0)->GetFormat() == AP4_SAMPLE_FORMAT_AC_4) ) { - trun_flags |= AP4_TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT; - first_sample_flags = 0x2000000; // sample_depends_on=2 (I frame) - } - AP4_TrunAtom* trun = new AP4_TrunAtom(trun_flags, 0, first_sample_flags); - + + // create the `trun` and `traf` atoms + AP4_TrunAtom* trun = new AP4_TrunAtom(trun_flags, 0, 0); unsigned int initial_offset = 0; - if(trun_version_one) { + if (trun_version_one) { trun->SetVersion(1); initial_offset = cursor->m_Sample.GetCtsDelta(); } - traf->AddChild(trun); moof->AddChild(traf); @@ -670,10 +667,12 @@ fragment->m_MdatSize = AP4_ATOM_HEADER_SIZE; AP4_UI32 constant_sample_duration = 0; bool all_sample_durations_equal = true; + bool all_samples_are_sync = true; + bool only_first_sample_is_sync = true; for (;;) { // if we have one non-zero CTS delta, we'll need to express it if (cursor->m_Sample.GetCtsDelta()) { - trun->SetFlags(trun->GetFlags() | AP4_TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT); + trun_flags |= AP4_TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT; } // add one sample @@ -687,6 +686,7 @@ next_unscaled_timestamp; trun_entry.sample_duration = (AP4_UI32)(next_scaled_timestamp-cursor->m_Timestamp); trun_entry.sample_size = cursor->m_Sample.GetSize(); + trun_entry.sample_flags = cursor->m_Sample.IsSync() ? sync_sample_flags : non_sync_sample_flags; trun_entry.sample_composition_time_offset = timescale? (AP4_UI32)AP4_ConvertTime(cursor->m_Sample.GetCtsDelta(), cursor->m_Track->GetMediaTimeScale(), @@ -712,6 +712,15 @@ } } + // update flag metadata + if (cursor->m_Sample.IsSync()) { + if (sample_count) { + only_first_sample_is_sync = false; + } + } else { + all_samples_are_sync = false; + } + // next sample cursor->m_UnscaledTimestamp = next_unscaled_timestamp; cursor->m_Timestamp = next_scaled_timestamp; @@ -736,14 +745,31 @@ printf(" constant sample duration: %s\n", all_sample_durations_equal?"yes":"no"); } - // update the 'trun' flags if needed + // update the flags + if (only_first_sample_is_sync) { + trun_flags |= AP4_TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT; + trun->SetFirstSampleFlags(sync_sample_flags); + tfhd_flags |= AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT; + tfhd->SetDefaultSampleFlags(non_sync_sample_flags); + } else { + if (all_samples_are_sync) { + tfhd_flags |= AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT; + tfhd->SetDefaultSampleFlags(0); + } else { + trun_flags |= AP4_TRUN_FLAG_SAMPLE_FLAGS_PRESENT; + } + } + if (all_sample_durations_equal) { + tfhd_flags |= AP4_TFHD_FLAG_DEFAULT_SAMPLE_DURATION_PRESENT; tfhd->SetDefaultSampleDuration(constant_sample_duration); - tfhd->UpdateFlags(tfhd->GetFlags() | AP4_TFHD_FLAG_DEFAULT_SAMPLE_DURATION_PRESENT); } else { - trun->SetFlags(trun->GetFlags() | AP4_TRUN_FLAG_SAMPLE_DURATION_PRESENT); + trun_flags |= AP4_TRUN_FLAG_SAMPLE_DURATION_PRESENT; } + tfhd->UpdateFlags(tfhd_flags); + trun->UpdateFlags(trun_flags); + // update moof and children trun->SetEntries(trun_entries); trun->SetDataOffset((AP4_UI32)moof->GetSize()+AP4_ATOM_HEADER_SIZE);
View file
bento4-1.6.0r638.tar.gz/Source/C++/Apps/Mp4Mux/Mp4Mux.cpp -> bento4-1.6.0r639.tar.gz/Source/C++/Apps/Mp4Mux/Mp4Mux.cpp
Changed
@@ -886,7 +886,7 @@ ac4Dsi); // AC-4 DSI sample_description_index = sample_table->GetSampleDescriptionCount(); sample_table->AddSampleDescription(sample_description); - /* sample_rate = */frame.m_Info.m_Ac4Dsi.d.v1.fs; + /* sample_rate = frame.m_Info.m_Ac4Dsi.d.v1.fs */; sample_duration = frame.m_Info.m_SampleDuration; media_time_scale = frame.m_Info.m_MediaTimeScale;
View file
bento4-1.6.0r638.tar.gz/Source/C++/Codecs/Ap4Ac3Parser.cpp -> bento4-1.6.0r639.tar.gz/Source/C++/Codecs/Ap4Ac3Parser.cpp
Changed
@@ -111,7 +111,7 @@ | +----------------------------------------------------------------------*/ bool -AP4_Ac3Header::MatchFixed(AP4_Ac3Header frame, AP4_Ac3Header next_frame) +AP4_Ac3Header::MatchFixed(AP4_Ac3Header& frame, AP4_Ac3Header& next_frame) { return true; }
View file
bento4-1.6.0r638.tar.gz/Source/C++/Codecs/Ap4Ac3Parser.h -> bento4-1.6.0r639.tar.gz/Source/C++/Codecs/Ap4Ac3Parser.h
Changed
@@ -79,7 +79,7 @@ AP4_UI08 m_addbsi[65]; // (addbsil+1)×8 // class methods - static bool MatchFixed(AP4_Ac3Header frame, AP4_Ac3Header next_frame); + static bool MatchFixed(AP4_Ac3Header& frame, AP4_Ac3Header& next_frame); }; typedef struct {
View file
bento4-1.6.0r638.tar.gz/Source/C++/Codecs/Ap4Ac4Parser.cpp -> bento4-1.6.0r639.tar.gz/Source/C++/Codecs/Ap4Ac4Parser.cpp
Changed
@@ -185,7 +185,7 @@ | +----------------------------------------------------------------------*/ bool -AP4_Ac4Header::MatchFixed(AP4_Ac4Header frame, AP4_Ac4Header next_frame) +AP4_Ac4Header::MatchFixed(AP4_Ac4Header& frame, AP4_Ac4Header& next_frame) { // Some parameter shall be const which defined in AC-4 in ISO-BMFF specs // TODO: More constraints will be added
View file
bento4-1.6.0r638.tar.gz/Source/C++/Codecs/Ap4Ac4Parser.h -> bento4-1.6.0r639.tar.gz/Source/C++/Codecs/Ap4Ac4Parser.h
Changed
@@ -88,7 +88,8 @@ // AC-4 Presentation Information AP4_Dac4Atom::Ac4Dsi::PresentationV1 *m_PresentationV1; // class methods - static bool MatchFixed(AP4_Ac4Header frame, AP4_Ac4Header next_frame); + static bool MatchFixed(AP4_Ac4Header& frame, AP4_Ac4Header& next_frame); + private: AP4_Result GetPresentationVersionBySGIndex(unsigned int substream_group_index); AP4_Result GetPresentationIndexBySGIndex (unsigned int substream_group_index);
View file
bento4-1.6.0r638.tar.gz/Source/C++/Codecs/Ap4Eac3Parser.cpp -> bento4-1.6.0r639.tar.gz/Source/C++/Codecs/Ap4Eac3Parser.cpp
Changed
@@ -309,7 +309,7 @@ | +----------------------------------------------------------------------*/ bool -AP4_Eac3Header::MatchFixed(AP4_Eac3Header frame, AP4_Eac3Header next_frame) +AP4_Eac3Header::MatchFixed(AP4_Eac3Header& frame, AP4_Eac3Header& next_frame) { if (frame.m_Acmod == next_frame.m_Acmod && frame.m_Bsid == next_frame.m_Bsid &&
View file
bento4-1.6.0r638.tar.gz/Source/C++/Codecs/Ap4Eac3Parser.h -> bento4-1.6.0r639.tar.gz/Source/C++/Codecs/Ap4Eac3Parser.h
Changed
@@ -79,7 +79,7 @@ AP4_UI08 m_Addbsi[65]; // (addbsil + 1)* 8 // class methods - static bool MatchFixed(AP4_Eac3Header frame, AP4_Eac3Header next_frame); + static bool MatchFixed(AP4_Eac3Header& frame, AP4_Eac3Header& next_frame); }; typedef struct {
View file
bento4-1.6.0r638.tar.gz/Source/C++/Core/Ap4TrunAtom.cpp -> bento4-1.6.0r639.tar.gz/Source/C++/Core/Ap4TrunAtom.cpp
Changed
@@ -89,7 +89,7 @@ m_DataOffset(data_offset), m_FirstSampleFlags(first_sample_flags) { - m_Size32 += 4*ComputeOptionalFieldsCount(flags); + m_Size32 += 4 * ComputeOptionalFieldsCount(flags); } /*---------------------------------------------------------------------- @@ -152,6 +152,16 @@ } /*---------------------------------------------------------------------- +| AP4_TrunAtom::UpdateFlags ++---------------------------------------------------------------------*/ +void +AP4_TrunAtom::UpdateFlags(AP4_UI32 flags) +{ + m_Flags = flags; + m_Size32 = AP4_FULL_ATOM_HEADER_SIZE + 4 + 4 * ComputeOptionalFieldsCount(flags); +} + +/*---------------------------------------------------------------------- | AP4_TrunAtom::SetEntries +---------------------------------------------------------------------*/ AP4_Result
View file
bento4-1.6.0r638.tar.gz/Source/C++/Core/Ap4TrunAtom.h -> bento4-1.6.0r639.tar.gz/Source/C++/Core/Ap4TrunAtom.h
Changed
@@ -71,15 +71,17 @@ AP4_TrunAtom(AP4_UI32 flags, AP4_SI32 data_offset, AP4_UI32 first_sample_flags); + void UpdateFlags(AP4_UI32 flags); virtual AP4_Result InspectFields(AP4_AtomInspector& inspector); virtual AP4_Result WriteFields(AP4_ByteStream& stream); // accessors - AP4_SI32 GetDataOffset() { return m_DataOffset; } - void SetDataOffset(AP4_SI32 offset) { m_DataOffset = offset; } - AP4_UI32 GetFirstSampleFlags() { return m_FirstSampleFlags; } - const AP4_Array<Entry>& GetEntries() { return m_Entries; } - AP4_Array<Entry>& UseEntries() { return m_Entries; } + AP4_SI32 GetDataOffset() { return m_DataOffset; } + void SetDataOffset(AP4_SI32 offset) { m_DataOffset = offset; } + AP4_UI32 GetFirstSampleFlags() { return m_FirstSampleFlags; } + void SetFirstSampleFlags(AP4_UI32 flags) { m_FirstSampleFlags = flags; } + const AP4_Array<Entry>& GetEntries() { return m_Entries; } + AP4_Array<Entry>& UseEntries() { return m_Entries; } AP4_Result SetEntries(const AP4_Array<Entry>& entries); private:
View file
bento4-1.6.0r638.tar.gz/Source/Python/utils/mp4-dash.py -> bento4-1.6.0r639.tar.gz/Source/Python/utils/mp4-dash.py
Changed
@@ -61,7 +61,7 @@ # setup main options VERSION = "2.0.0" -SDK_REVISION = '638' +SDK_REVISION = '639' SCRIPT_PATH = path.abspath(path.dirname(__file__)) sys.path += [SCRIPT_PATH]
View file
bento4-1.6.0r638.tar.gz/Source/Python/utils/mp4-hls.py -> bento4-1.6.0r639.tar.gz/Source/Python/utils/mp4-hls.py
Changed
@@ -31,7 +31,7 @@ # setup main options VERSION = "1.2.0" -SDK_REVISION = '638' +SDK_REVISION = '639' SCRIPT_PATH = path.abspath(path.dirname(__file__)) sys.path += [SCRIPT_PATH]
View file
bento4-1.6.0r638.tar.gz/tasks/doc.py -> bento4-1.6.0r639.tar.gz/tasks/doc.py
Changed
@@ -1,8 +1,6 @@ """Tasks to build the Bento4 documentation""" import os -import sys -import shutil from invoke import task, Collection @task(default=True)
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.