diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index 57b25005e..a770e47c6 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -1049,6 +1049,7 @@ public class DownloadDialog extends DialogFragment final Stream selectedStream; Stream secondaryStream = null; final char kind; + final boolean embedMetadata = dialogBinding.metadataSwitch.isChecked(); int threads = dialogBinding.threads.getProgress() + 1; final String[] urls; final List recoveryInfo; @@ -1136,8 +1137,8 @@ public class DownloadDialog extends DialogFragment ); } - DownloadManagerService.startMission(context, urls, storage, kind, threads, - currentInfo, psName, psArgs, nearLength, new ArrayList<>(recoveryInfo)); + DownloadManagerService.startMission(context, urls, storage, kind, threads, currentInfo, + psName, embedMetadata, psArgs, nearLength, new ArrayList<>(recoveryInfo)); Toast.makeText(context, getString(R.string.download_has_started), Toast.LENGTH_SHORT).show(); diff --git a/app/src/main/java/org/schabi/newpipe/streams/Mp4FromDashWriter.java b/app/src/main/java/org/schabi/newpipe/streams/Mp4FromDashWriter.java index 73bd51e3d..7094d672d 100644 --- a/app/src/main/java/org/schabi/newpipe/streams/Mp4FromDashWriter.java +++ b/app/src/main/java/org/schabi/newpipe/streams/Mp4FromDashWriter.java @@ -64,9 +64,11 @@ public class Mp4FromDashWriter { private final ArrayList compatibleBrands = new ArrayList<>(5); + private final boolean embedMetadata; private final Mp4MetadataHelper metadataHelper; - public Mp4FromDashWriter(final StreamInfo streamInfo, + public Mp4FromDashWriter(final boolean embedMetadata, + final StreamInfo streamInfo, final Bitmap thumbnail, final SharpStream... sources) throws IOException { for (final SharpStream src : sources) { @@ -75,6 +77,7 @@ public class Mp4FromDashWriter { } } + this.embedMetadata = embedMetadata; this.metadataHelper = new Mp4MetadataHelper( this::auxOffset, buffer -> { @@ -750,7 +753,9 @@ public class Mp4FromDashWriter { makeMvhd(longestTrack); - metadataHelper.makeUdta(); + if (embedMetadata) { + metadataHelper.makeUdta(); + } for (int i = 0; i < tracks.length; i++) { if (tracks[i].trak.tkhd.matrix.length != 36) { diff --git a/app/src/main/java/org/schabi/newpipe/streams/OggFromWebMWriter.java b/app/src/main/java/org/schabi/newpipe/streams/OggFromWebMWriter.java index c043fff87..e39a0ada7 100644 --- a/app/src/main/java/org/schabi/newpipe/streams/OggFromWebMWriter.java +++ b/app/src/main/java/org/schabi/newpipe/streams/OggFromWebMWriter.java @@ -121,6 +121,7 @@ public class OggFromWebMWriter implements Closeable { private long segmentTableNextTimestamp = TIME_SCALE_NS; private final int[] crc32Table = new int[256]; + private final boolean embedMetadata; private final StreamInfo streamInfo; private final Bitmap thumbnail; @@ -128,11 +129,13 @@ public class OggFromWebMWriter implements Closeable { * Constructor of OggFromWebMWriter. * @param source * @param target + * @param embedMetadata whether to embed metadata in the output Ogg stream * @param streamInfo the stream info * @param thumbnail the thumbnail bitmap used as cover art */ public OggFromWebMWriter(@NonNull final SharpStream source, @NonNull final SharpStream target, + final boolean embedMetadata, @Nullable final StreamInfo streamInfo, @Nullable final Bitmap thumbnail) { if (!source.canRead() || !source.canRewind()) { @@ -144,6 +147,7 @@ public class OggFromWebMWriter implements Closeable { this.source = source; this.output = target; + this.embedMetadata = embedMetadata; this.streamInfo = streamInfo; this.thumbnail = thumbnail; @@ -264,9 +268,11 @@ public class OggFromWebMWriter implements Closeable { } /* step 3: create packet with metadata */ - final byte[] buffer = makeCommentHeader(); - if (buffer != null) { - addPacketSegmentMultiPage(buffer, header); + if (embedMetadata) { + final byte[] buffer = makeCommentHeader(); + if (buffer != null) { + addPacketSegmentMultiPage(buffer, header); + } } /* step 4: calculate amount of packets */ diff --git a/app/src/main/java/us/shandian/giga/postprocessing/M4aNoDash.java b/app/src/main/java/us/shandian/giga/postprocessing/M4aNoDash.java index ec57ed491..d05d5c235 100644 --- a/app/src/main/java/us/shandian/giga/postprocessing/M4aNoDash.java +++ b/app/src/main/java/us/shandian/giga/postprocessing/M4aNoDash.java @@ -31,7 +31,7 @@ class M4aNoDash extends Postprocessing { @Override int process(SharpStream out, SharpStream... sources) throws IOException { Mp4FromDashWriter muxer = new Mp4FromDashWriter( - this.streamInfo, this.thumbnail, sources[0]); + this.embedMetadata, this.streamInfo, this.thumbnail, sources[0]); muxer.setMainBrand(0x4D344120);// binary string "M4A " muxer.parseSources(); muxer.selectTracks(0); diff --git a/app/src/main/java/us/shandian/giga/postprocessing/Mp3Metadata.java b/app/src/main/java/us/shandian/giga/postprocessing/Mp3Metadata.java index a839de582..b585cc139 100644 --- a/app/src/main/java/us/shandian/giga/postprocessing/Mp3Metadata.java +++ b/app/src/main/java/us/shandian/giga/postprocessing/Mp3Metadata.java @@ -31,6 +31,11 @@ public class Mp3Metadata extends Postprocessing { super(true, true, ALGORITHM_MP3_METADATA); } + @Override + boolean test(SharpStream... sources) { + return this.embedMetadata; + } + @Override int process(SharpStream out, SharpStream... sources) throws IOException { if (sources == null || sources.length == 0 || sources[0] == null) { diff --git a/app/src/main/java/us/shandian/giga/postprocessing/Mp4FromDashMuxer.java b/app/src/main/java/us/shandian/giga/postprocessing/Mp4FromDashMuxer.java index 887ba1bf5..43333f1cb 100644 --- a/app/src/main/java/us/shandian/giga/postprocessing/Mp4FromDashMuxer.java +++ b/app/src/main/java/us/shandian/giga/postprocessing/Mp4FromDashMuxer.java @@ -16,7 +16,8 @@ class Mp4FromDashMuxer extends Postprocessing { @Override int process(SharpStream out, SharpStream... sources) throws IOException { - Mp4FromDashWriter muxer = new Mp4FromDashWriter(this.streamInfo, this.thumbnail, sources); + Mp4FromDashWriter muxer = new Mp4FromDashWriter( + this.embedMetadata, this.streamInfo, this.thumbnail, sources); muxer.parseSources(); muxer.selectTracks(0, 0); muxer.build(out); diff --git a/app/src/main/java/us/shandian/giga/postprocessing/Mp4Metadata.java b/app/src/main/java/us/shandian/giga/postprocessing/Mp4Metadata.java index f03c88b5a..40fa15f29 100644 --- a/app/src/main/java/us/shandian/giga/postprocessing/Mp4Metadata.java +++ b/app/src/main/java/us/shandian/giga/postprocessing/Mp4Metadata.java @@ -27,6 +27,9 @@ public class Mp4Metadata extends Postprocessing { @Override boolean test(SharpStream... sources) throws IOException { + // nothing to do if metadata should not be embedded + if (!embedMetadata) return false; + // quick check: ensure there's at least one source and it looks like an MP4, // i.e. the file has a 'moov' box near the beginning. // THe 'udta' box is inserted inside 'moov', so if there's no 'moov' we can't do anything. diff --git a/app/src/main/java/us/shandian/giga/postprocessing/OggFromWebmDemuxer.java b/app/src/main/java/us/shandian/giga/postprocessing/OggFromWebmDemuxer.java index f76fadb31..d4d0c4637 100644 --- a/app/src/main/java/us/shandian/giga/postprocessing/OggFromWebmDemuxer.java +++ b/app/src/main/java/us/shandian/giga/postprocessing/OggFromWebmDemuxer.java @@ -35,7 +35,7 @@ class OggFromWebmDemuxer extends Postprocessing { @Override int process(SharpStream out, @NonNull SharpStream... sources) throws IOException { OggFromWebMWriter demuxer = new OggFromWebMWriter( - sources[0], out, streamInfo, thumbnail); + sources[0], out, embedMetadata, streamInfo, thumbnail); demuxer.parseSource(); demuxer.selectTrack(0); demuxer.build(); diff --git a/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java b/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java index 3cb8b530c..ae1068c3a 100644 --- a/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java +++ b/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java @@ -35,7 +35,9 @@ public abstract class Postprocessing implements Serializable { public static final String ALGORITHM_M4A_NO_DASH = "mp4D-m4a"; public static final String ALGORITHM_OGG_FROM_WEBM_DEMUXER = "webm-ogg-d"; - public static Postprocessing getAlgorithm(@NonNull String algorithmName, String[] args, + public static Postprocessing getAlgorithm(@NonNull String algorithmName, + boolean embedMetadata, + String[] args, @NonNull StreamInfo streamInfo) { Postprocessing instance; @@ -67,6 +69,7 @@ public abstract class Postprocessing implements Serializable { instance.args = args; instance.streamInfo = streamInfo; + instance.embedMetadata = embedMetadata; return instance; } @@ -88,6 +91,11 @@ public abstract class Postprocessing implements Serializable { private String[] args; + /** + * Indicates whether the metadata should be embedded in the file or not. + */ + boolean embedMetadata; + /** * StreamInfo object related to the current download */ diff --git a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java index 6ce6a4b38..3cf55e156 100755 --- a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java @@ -40,7 +40,6 @@ import androidx.preference.PreferenceManager; import org.schabi.newpipe.R; import org.schabi.newpipe.download.DownloadActivity; -import org.schabi.newpipe.extractor.Image; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.player.helper.LockManager; import org.schabi.newpipe.streams.io.StoredDirectoryHelper; @@ -75,6 +74,7 @@ public class DownloadManagerService extends Service { private static final String EXTRA_KIND = "DownloadManagerService.extra.kind"; private static final String EXTRA_THREADS = "DownloadManagerService.extra.threads"; private static final String EXTRA_POSTPROCESSING_NAME = "DownloadManagerService.extra.postprocessingName"; + private static final String EXTRA_POSTPROCESSING_METADATA = "DownloadManagerService.extra.postprocessingMetadata"; private static final String EXTRA_POSTPROCESSING_ARGS = "DownloadManagerService.extra.postprocessingArgs"; private static final String EXTRA_NEAR_LENGTH = "DownloadManagerService.extra.nearLength"; private static final String EXTRA_PATH = "DownloadManagerService.extra.storagePath"; @@ -349,20 +349,21 @@ public class DownloadManagerService extends Service { /** * Start a new download mission * - * @param context the activity context - * @param urls array of urls to download - * @param storage where the file is saved - * @param kind type of file (a: audio v: video s: subtitle ?: file-extension defined) - * @param threads the number of threads maximal used to download chunks of the file. - * @param psName the name of the required post-processing algorithm, or {@code null} to ignore. - * @param streamInfo stream metadata that may be written into the downloaded file. - * @param psArgs the arguments for the post-processing algorithm. - * @param nearLength the approximated final length of the file - * @param recoveryInfo array of MissionRecoveryInfo, in case is required recover the download + * @param context the activity context + * @param urls array of urls to download + * @param storage where the file is saved + * @param kind type of file (a: audio v: video s: subtitle ?: file-extension defined) + * @param threads the number of threads maximal used to download chunks of the file. + * @param streamInfo stream metadata that may be written into the downloaded file. + * @param psName the name of the required post-processing algorithm, or {@code null} to ignore. + * @param embedMetadata whether the metadata should be embedded into the downloaded file. + * @param psArgs the arguments for the post-processing algorithm. + * @param nearLength the approximated final length of the file + * @param recoveryInfo array of MissionRecoveryInfo, in case is required recover the download */ public static void startMission(Context context, String[] urls, StoredFileHelper storage, char kind, int threads, StreamInfo streamInfo, String psName, - String[] psArgs, long nearLength, + boolean embedMetadata, String[] psArgs, long nearLength, ArrayList recoveryInfo) { final Intent intent = new Intent(context, DownloadManagerService.class) .setAction(Intent.ACTION_RUN) @@ -370,6 +371,7 @@ public class DownloadManagerService extends Service { .putExtra(EXTRA_KIND, kind) .putExtra(EXTRA_THREADS, threads) .putExtra(EXTRA_POSTPROCESSING_NAME, psName) + .putExtra(EXTRA_POSTPROCESSING_METADATA, embedMetadata) .putExtra(EXTRA_POSTPROCESSING_ARGS, psArgs) .putExtra(EXTRA_NEAR_LENGTH, nearLength) .putExtra(EXTRA_RECOVERY_INFO, recoveryInfo) @@ -388,6 +390,7 @@ public class DownloadManagerService extends Service { int threads = intent.getIntExtra(EXTRA_THREADS, 1); char kind = intent.getCharExtra(EXTRA_KIND, '?'); String psName = intent.getStringExtra(EXTRA_POSTPROCESSING_NAME); + boolean embedMetadata = intent.getBooleanExtra(EXTRA_POSTPROCESSING_METADATA, false); String[] psArgs = intent.getStringArrayExtra(EXTRA_POSTPROCESSING_ARGS); long nearLength = intent.getLongExtra(EXTRA_NEAR_LENGTH, 0); String tag = intent.getStringExtra(EXTRA_STORAGE_TAG); @@ -407,7 +410,7 @@ public class DownloadManagerService extends Service { if (psName == null) ps = null; else - ps = Postprocessing.getAlgorithm(psName, psArgs, streamInfo); + ps = Postprocessing.getAlgorithm(psName, embedMetadata, psArgs, streamInfo); final DownloadMission mission = new DownloadMission( urls, storage, kind, ps, streamInfo, getApplicationContext()); diff --git a/app/src/main/res/layout/download_dialog.xml b/app/src/main/res/layout/download_dialog.xml index 67aa1577c..5541d6545 100644 --- a/app/src/main/res/layout/download_dialog.xml +++ b/app/src/main/res/layout/download_dialog.xml @@ -105,11 +105,21 @@ android:text="@string/audio_track_present_in_video" android:textSize="12sp" /> + + No download folder set yet, choose the default download folder now This permission is needed to\nopen in popup mode 1 item deleted. + Embed metadata such as title, author, thumbnail reCAPTCHA challenge Press \"Done\" when solved