<commit_before>/*******************************************************************************
 * Copyright (c) 2014, <NAME>.  All rights reserved.
 *  
 * This file is part of Humble-Video.
 *
 * Humble-Video is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Humble-Video 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Humble-Video.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package io.humble.video_demos;

import java.io.IOException;

import io.humble.video.Codec;
import io.humble.video.Decoder;
import io.humble.video.Demuxer;
import io.humble.video.DemuxerFormat;
import io.humble.video.DemuxerStream;
import io.humble.video.Global;
import io.humble.video.KeyValueBag;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

/**
 * Demo application that takes a Media file and displays the known meta-data about it.
 * @author aclarke
 */
public class GetContainerInfo {

  /**
   * Takes a media container (file) as the first argument, opens it,
   * and tells you what's inside the container.
   * 
   * To run from maven, do:
   * <pre>
   * mvn install exec:java -Dexec.mainClass="io.humble.video_demos.GetContainerInfo" -Dexec.args="filename.mp4"
   * </pre>
   * @param args Must contain one string which represents a filename. If no arguments, then prints help.
   * @throws IOException if file cannot be opened.
   * @throws InterruptedException if process is interrupted while querying.
   */
  public static void main(String[] args) throws InterruptedException, IOException {
    final Options options = new Options();
    options.addOption("h", "help", false, "displays help");
    options.addOption("v", "version", false, "version of this library");
    
    final CommandLineParser parser = new org.apache.commons.cli.BasicParser();
    try {
      final CommandLine cmd = parser.parse(options, args);
      if (cmd.hasOption("version")) {
        // let's find what version of the library we're running
        final String version = io.humble.video_native.Version.getVersionInfo();
        System.out.println("Humble Version: " + version);
      } else if (cmd.hasOption("help") || args.length == 0) {
        final HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp(GetContainerInfo.class.getCanonicalName() + " <filename>", options);
      } else {
        final String[] parsedArgs = cmd.getArgs();
        for(String arg: parsedArgs)
          getInfo(arg, options);
      }
    } catch (ParseException e) {
      System.err.println("Exception parsing command line: " + e.getLocalizedMessage());
    }
  }

  /**
   * Parse information from a file, and also optionally print information about what
   * formats, containers and codecs fit into that file.
   * 
   * @param arg The file to open, or null if we just want generic options.
   * @param options A set of command line options passed in.
   * @throws IOException if file cannot be opened.
   * @throws InterruptedException if process is interrupted while querying.
   */
  private static void getInfo(String arg, Options options) throws InterruptedException, IOException {
    final Demuxer container = Demuxer.make();
    // attempt to open the container. Notes that we assume no extra streams
    // can be added, and that we should attempt to query StreamMetaData (false and true
    // respectively).
    container.open(arg, null, false, true, null, null);
    final DemuxerFormat format = container.getFormat();
    System.out.printf("URL: '%s' (%s: %s)\n", container.getURL(), format.getLongName(), format.getName());

    // get metadata
    KeyValueBag metadata = container.getMetaData();
    System.out.println("MetaData:");
    for(String key: metadata.getKeys())
      System.out.printf("  %s: %s\n", key, metadata.getValue(key));

    // print out some basics about the container
    final String formattedDuration = formatTimeStamp(container.getDuration());
    System.out.printf("Duration: %s, start: %f, bitrate: %d kb/s\n",
        formattedDuration,
        container.getStartTime() == Global.NO_PTS ? 0 : container.getStartTime() / 1000000.0,
            container.getBitRate()/1000);
    
    // now, let's print out details on each stream.
    int ns = container.getNumStreams();
    for (int i = 0; i < ns; i++) {
      DemuxerStream stream = container.getStream(i);
      Decoder d = stream.getDecoder();
      System.out.printf(" Stream #0.%1$d (%s): %s\n", i, d != null ? d.toString() : "unknown coder");
      System.out.println("  Metadata:");
      metadata = stream.getMetaData();
      for(String key: metadata.getKeys())
        System.out.printf("  %s: %s\n", key, metadata.getValue(key));
    }
  }

  /**
   * @param duration
   * @return
   */
  private static String formatTimeStamp(long duration) {
    if (duration == Global.NO_PTS) {
      return "00:00:00.00";
    }
    double d = 1.0 * duration / Global.DEFAULT_PTS_PER_SECOND;
    int hours = (int) (d / (60*60));
    int mins = (int) ((d - hours*60*60) / 60);
    int secs = (int) (d - hours*60*60 - mins*60);
    int subsecs = (int)((d - (hours*60*60.0 + mins*60.0 + secs))*100.0);
    return String.format("%1$02d:%2$02d:%3$02d.%4$02d", hours, mins, secs, subsecs);
  }
}<commit_msg>Clean up code, add comments, and basically make it a worth demo.<commit_after>/*******************************************************************************
 * Copyright (c) 2014, <NAME>.  All rights reserved.
 *  
 * This file is part of Humble-Video.
 *
 * Humble-Video is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Humble-Video 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Humble-Video.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package io.humble.video_demos;

import java.io.IOException;

import io.humble.video.Decoder;
import io.humble.video.Demuxer;
import io.humble.video.DemuxerFormat;
import io.humble.video.DemuxerStream;
import io.humble.video.Global;
import io.humble.video.KeyValueBag;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

/**
 * Demo application that takes a Media file and displays the known meta-data about it.
 * @author aclarke
 */
public class GetContainerInfo {

  /**
   * Takes a media container (file) as the first argument, opens it,
   * and tells you what's inside the container.
   * 
   * To run from maven, do:
   * <pre>
   * mvn install exec:java -Dexec.mainClass="io.humble.video_demos.GetContainerInfo" -Dexec.args="filename.mp4"
   * </pre>
   * @param args Must contain one string which represents a filename. If no arguments, then prints help.
   * @throws IOException if file cannot be opened.
   * @throws InterruptedException if process is interrupted while querying.
   */
  public static void main(String[] args) throws InterruptedException, IOException {
    final Options options = new Options();
    options.addOption("h", "help", false, "displays help");
    options.addOption("v", "version", false, "version of this library");
    
    final CommandLineParser parser = new org.apache.commons.cli.BasicParser();
    try {
      final CommandLine cmd = parser.parse(options, args);
      if (cmd.hasOption("version")) {
        // let's find what version of the library we're running
        final String version = io.humble.video_native.Version.getVersionInfo();
        System.out.println("Humble Version: " + version);
      } else if (cmd.hasOption("help") || args.length == 0) {
        final HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp(GetContainerInfo.class.getCanonicalName() + " <filename>", options);
      } else {
        final String[] parsedArgs = cmd.getArgs();
        for(String arg: parsedArgs)
          getInfo(arg, options);
      }
    } catch (ParseException e) {
      System.err.println("Exception parsing command line: " + e.getLocalizedMessage());
    }
  }

  /**
   * Parse information from a file, and also optionally print information about what
   * formats, containers and codecs fit into that file.
   * 
   * @param arg The file to open, or null if we just want generic options.
   * @param options A set of command line options passed in.
   * @throws IOException if file cannot be opened.
   * @throws InterruptedException if process is interrupted while querying.
   */
  private static void getInfo(String arg, Options options) throws InterruptedException, IOException {
    // In Humble, all objects have special contructors named 'make'.
    
    // A Demuxer opens up media containers, parses  and de-multiplexes the streams
    // of media data without those containers.
    final Demuxer demuxer = Demuxer.make();

    // We open the demuxer by pointing it at a URL.
    demuxer.open(arg, null, false, true, null, null);
    
    // Once we've opened a demuxer, Humble can make a guess about the
    // DemuxerFormat. Humble supports over 100+ media container formats.
    final DemuxerFormat format = demuxer.getFormat();
    System.out.printf("URL: '%s' (%s: %s)\n", demuxer.getURL(), format.getLongName(), format.getName());

    // Many programs that make containers, such as iMovie or Adobe Elements, will
    // insert meta-data about the container. Here we extract that meta data and print it.
    KeyValueBag metadata = demuxer.getMetaData();
    System.out.println("MetaData:");
    for(String key: metadata.getKeys())
      System.out.printf("  %s: %s\n", key, metadata.getValue(key));

    // There are a few other key pieces of information that are interesting for
    // most containers; The duration, the starting time, and the estimated bit-rate.
    // This code extracts all three.
    final String formattedDuration = formatTimeStamp(demuxer.getDuration());
    System.out.printf("Duration: %s, start: %f, bitrate: %d kb/s\n",
        formattedDuration,
        demuxer.getStartTime() == Global.NO_PTS ? 0 : demuxer.getStartTime() / 1000000.0,
            demuxer.getBitRate()/1000);
    
    // Finally, a container consists of several different independent streams of
    // data called Streams. In Humble there are two objects that represent streams:
    // DemuxerStream (when you are reading) and MuxerStreams (when you are writing).
    
    // First find the number of streams in this container.
    int ns = demuxer.getNumStreams();
    
    // Now, let's iterate through each of them.
    for (int i = 0; i < ns; i++) {
      DemuxerStream stream = demuxer.getStream(i);

      metadata = stream.getMetaData();
      // Language is usually embedded as metadata in a stream.
      final String language = metadata.getValue("language");
      
      // We will only be able to make a decoder for streams we can actually
      // decode, so the caller should check for null.
      Decoder d = stream.getDecoder();

      System.out.printf(" Stream #0.%1$d (%2$s): %3$s\n", i, language, d != null ? d.toString() : "unknown coder");
      System.out.println("  Metadata:");
      for(String key: metadata.getKeys())
        System.out.printf("    %s: %s\n", key, metadata.getValue(key));
    }
  }

  /**
   * Pretty prints a timestamp (in {@link Global.NO_PTS} units) into a string.
   * @param duration A timestamp in {@link Global.NO_PTS} units).
   * @return A string representing the duration.
   */
  private static String formatTimeStamp(long duration) {
    if (duration == Global.NO_PTS) {
      return "00:00:00.00";
    }
    double d = 1.0 * duration / Global.DEFAULT_PTS_PER_SECOND;
    int hours = (int) (d / (60*60));
    int mins = (int) ((d - hours*60*60) / 60);
    int secs = (int) (d - hours*60*60 - mins*60);
    int subsecs = (int)((d - (hours*60*60.0 + mins*60.0 + secs))*100.0);
    return String.format("%1$02d:%2$02d:%3$02d.%4$02d", hours, mins, secs, subsecs);
  }
}
{'fraction_non_alphanumeric': 0.1363878935732256, 'fraction_numerical': 0.011511778607913395, 'mean_word_length': 3.3843582887700534, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1466349', 'n_tokens_mistral': 3887, 'n_tokens_neox': 3729, 'n_words': 1299}