<commit_before>package misc;

import configuration.Settings;
import io.humble.video.*;
import io.humble.video.awt.MediaPictureConverter;
import io.humble.video.awt.MediaPictureConverterFactory;
import javafx.application.Platform;
import javafx.scene.control.TextArea;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Objects;

public class VideoDecoder {
    private final Settings settings;
    private final TextArea outputArea;
    private StringBuilder outputAreaText = new StringBuilder();

    private int numBlockColumns;
    private int numBlockRows;
    private int bitsPerFrame;
    private int bytesPerFrame;

    /**
     * Constructs a new VideoEncoder.
     *
     * @param settings
     *          The settings.
     *
     * @throws NullPointerException
     *          If the settings or outputArea are null.
     *
     * @throws IllegalStateException
     *          If there's an issue with the encoding settings.
     */
    public VideoDecoder(final Settings settings, final TextArea outputArea) throws IllegalStateException {
        Objects.requireNonNull(settings);
        Objects.requireNonNull(outputArea);

        this.settings = settings;
        this.outputArea = outputArea;
    }

    public void decode(final File inputFile, final File outputFile) throws IOException, InterruptedException {
        final Demuxer demuxer = Demuxer.make();
        demuxer.open(inputFile.getAbsolutePath(), null, false, true, null, null);

        // Retrieve the Decoder for the first video stream of the file.
        Decoder decoder = null;
        int streamId = -1;

        for (int i = 0 ; i < demuxer.getNumStreams() ; i++) {
            final DemuxerStream stream = demuxer.getStream(i);
            decoder = stream.getDecoder();

            if (decoder != null) {
                if (decoder.getCodecType() == MediaDescriptor.Type.MEDIA_VIDEO) {
                    streamId = i;
                    break;
                }
            }
        }

        if (decoder == null || streamId == -1) {
            // todo Throw an error, there's no video stream
            System.err.println("There's no video stream. decode VideoDecoder");
            System.exit(1);
        }

        decoder.open(null, null);

        outputAreaText.append("Decode Info:");
        outputAreaText.append("\n\tInput File: ").append(inputFile.getAbsolutePath());
        outputAreaText.append("\n\tOutput File: ").append(outputFile.getAbsolutePath());

        final FrameDimension frameDimensions = FrameDimension.getFrameDimension(decoder.getWidth(), decoder.getHeight());

        if (frameDimensions == null) {
            // todo Video doesn't match any of the accepted FrameDimension's, so it's
            // todo probably not a video made by Schillsaver.
            System.err.println("Video probs not made by Schillsaver. VideoDecoder|FrameDimensions");
            System.exit(1);
        }


        final FrameRate frameRate = FrameRate.getFrameRate(decoder.getTimeBase());

        if (frameRate == null) {
            // todo Video doesn't match any of the accept FrameRate's, so it's probably
            // todo not a video made by Schillsaver.
            System.err.println("Video probs not made by Schillsaver. VideoDecoder|FrameRate");
            System.exit(1);
        }

        final PixelFormat.Type pixelFormat = decoder.getPixelFormat();
        final Dimension blockDimensions = settings.getBlockDimensions().getBlockSize();

        numBlockRows = frameDimensions.getHeight() / blockDimensions.height;
        numBlockColumns = frameDimensions.getWidth() / blockDimensions.width;
        bytesPerFrame = numBlockColumns * numBlockRows;
        bitsPerFrame = bytesPerFrame/ 8;

        outputAreaText.append("\n\nSettings:");
        outputAreaText.append("\n\tFormat: ZIP");
        outputAreaText.append("\n\tCodec: ").append(decoder.getCodec().getName());
        outputAreaText.append("\n\tFrame Rate Enum: ").append(frameRate.name());
        outputAreaText.append("\n\tFrame Rate: ").append(decoder.getTimeBase().getDenominator());
        outputAreaText.append("\n\tFrame Dimensions Enum: ").append(frameDimensions.name());
        outputAreaText.append("\n\tFrame Width: ").append(frameDimensions.getWidth());
        outputAreaText.append("\n\tFrame Height: ").append(frameDimensions.getHeight());
        outputAreaText.append("\n\tFrame Count: ").append(decoder.getFrameCount());
        outputAreaText.append("\n\tPixel Format: ").append(pixelFormat.name());
        outputAreaText.append("\n\nDecode Progress:");

        final MediaPicture picture = MediaPicture.make(frameDimensions.getWidth(), frameDimensions.getHeight(), pixelFormat);
        final MediaPictureConverter converter = MediaPictureConverterFactory.createConverter(MediaPictureConverterFactory.HUMBLE_BGR_24, picture);
        final MediaPacket packet = MediaPacket.make();
        BufferedImage frameImage = null;

        try (
            final FileOutputStream fos = new FileOutputStream(outputFile);
        ) {
            final int totalFrames = decoder.getFrameCount();
            int frame = 0;

            while (demuxer.read(packet) >= 0) {
                if (packet.getStreamIndex() == streamId) {
                    int offset = 0;
                    int bytesRead = 0;

                    do {
                        bytesRead += decoder.decode(picture, packet, offset);

                        if (picture.isComplete()) {
                            frameImage = converter.toImage(frameImage, picture);

                            final byte[] bytes = decodeFrame(frameImage);
                            fos.write(bytes);
                        }

                        offset += bytesRead;
                    } while (offset < packet.getSize());

                    frame++;
                    final int finalFrame = frame - 1;
                    Platform.runLater(() -> outputArea.setText(outputAreaText + "\n\tProcessed Frames: " + finalFrame + "/" + totalFrames));
                }
            }

            fos.flush();

            /*
             * Some video decoders will cache video data before they begin decoding, so
             * when you're done, you need to flush them.
             *
             * The convention to flush encoders/decoders in Humble Video is to keep
             * passing in null until incomplete samples or packets are returned.
             */
            do {
                decoder.decode(picture, null, 0);
            } while (picture.isComplete());
        } catch (final IOException e) {
            // todo Alert the user to this issue
            final Logger logger = LogManager.getLogger();<commit_msg>Removes frame count.<commit_after>package misc;

import configuration.Settings;
import io.humble.video.*;
import io.humble.video.awt.MediaPictureConverter;
import io.humble.video.awt.MediaPictureConverterFactory;
import javafx.application.Platform;
import javafx.scene.control.TextArea;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Objects;

public class VideoDecoder {
    private final Settings settings;
    private final TextArea outputArea;
    private StringBuilder outputAreaText = new StringBuilder();

    private int numBlockColumns;
    private int numBlockRows;
    private int bitsPerFrame;
    private int bytesPerFrame;

    /**
     * Constructs a new VideoEncoder.
     *
     * @param settings
     *          The settings.
     *
     * @throws NullPointerException
     *          If the settings or outputArea are null.
     *
     * @throws IllegalStateException
     *          If there's an issue with the encoding settings.
     */
    public VideoDecoder(final Settings settings, final TextArea outputArea) throws IllegalStateException {
        Objects.requireNonNull(settings);
        Objects.requireNonNull(outputArea);

        this.settings = settings;
        this.outputArea = outputArea;
    }

    public void decode(final File inputFile, final File outputFile) throws IOException, InterruptedException {
        final Demuxer demuxer = Demuxer.make();
        demuxer.open(inputFile.getAbsolutePath(), null, false, true, null, null);

        // Retrieve the Decoder for the first video stream of the file.
        Decoder decoder = null;
        int streamId = -1;

        for (int i = 0 ; i < demuxer.getNumStreams() ; i++) {
            final DemuxerStream stream = demuxer.getStream(i);
            decoder = stream.getDecoder();

            if (decoder != null) {
                if (decoder.getCodecType() == MediaDescriptor.Type.MEDIA_VIDEO) {
                    streamId = i;
                    break;
                }
            }
        }

        if (decoder == null || streamId == -1) {
            // todo Throw an error, there's no video stream
            System.err.println("There's no video stream. decode VideoDecoder");
            System.exit(1);
        }

        decoder.open(null, null);

        outputAreaText.append("Decode Info:");
        outputAreaText.append("\n\tInput File: ").append(inputFile.getAbsolutePath());
        outputAreaText.append("\n\tOutput File: ").append(outputFile.getAbsolutePath());

        final FrameDimension frameDimensions = FrameDimension.getFrameDimension(decoder.getWidth(), decoder.getHeight());

        if (frameDimensions == null) {
            // todo Video doesn't match any of the accepted FrameDimension's, so it's
            // todo probably not a video made by Schillsaver.
            System.err.println("Video probs not made by Schillsaver. VideoDecoder|FrameDimensions");
            System.exit(1);
        }


        final FrameRate frameRate = FrameRate.getFrameRate(decoder.getTimeBase());

        if (frameRate == null) {
            // todo Video doesn't match any of the accept FrameRate's, so it's probably
            // todo not a video made by Schillsaver.
            System.err.println("Video probs not made by Schillsaver. VideoDecoder|FrameRate");
            System.exit(1);
        }

        final PixelFormat.Type pixelFormat = decoder.getPixelFormat();
        final Dimension blockDimensions = settings.getBlockDimensions().getBlockSize();

        numBlockRows = frameDimensions.getHeight() / blockDimensions.height;
        numBlockColumns = frameDimensions.getWidth() / blockDimensions.width;
        bytesPerFrame = numBlockColumns * numBlockRows;
        bitsPerFrame = bytesPerFrame/ 8;

        outputAreaText.append("\n\nSettings:");
        outputAreaText.append("\n\tFormat: ZIP");
        outputAreaText.append("\n\tCodec: ").append(decoder.getCodec().getName());
        outputAreaText.append("\n\tFrame Rate Enum: ").append(frameRate.name());
        outputAreaText.append("\n\tFrame Rate: ").append(decoder.getTimeBase().getDenominator());
        outputAreaText.append("\n\tFrame Dimensions Enum: ").append(frameDimensions.name());
        outputAreaText.append("\n\tFrame Width: ").append(frameDimensions.getWidth());
        outputAreaText.append("\n\tFrame Height: ").append(frameDimensions.getHeight());
        outputAreaText.append("\n\tPixel Format: ").append(pixelFormat.name());
        outputAreaText.append("\n\nDecode Progress:");

        final MediaPicture picture = MediaPicture.make(frameDimensions.getWidth(), frameDimensions.getHeight(), pixelFormat);
        final MediaPictureConverter converter = MediaPictureConverterFactory.createConverter(MediaPictureConverterFactory.HUMBLE_BGR_24, picture);
        final MediaPacket packet = MediaPacket.make();
        BufferedImage frameImage = null;

        try (
            final FileOutputStream fos = new FileOutputStream(outputFile);
        ) {
            int frame = 0;

            while (demuxer.read(packet) >= 0) {
                if (packet.getStreamIndex() == streamId) {
                    int offset = 0;
                    int bytesRead = 0;

                    do {
                        bytesRead += decoder.decode(picture, packet, offset);

                        if (picture.isComplete()) {
                            frameImage = converter.toImage(frameImage, picture);

                            final byte[] bytes = decodeFrame(frameImage);
                            fos.write(bytes);
                        }

                        offset += bytesRead;
                    } while (offset < packet.getSize());

                    frame++;
                    final int finalFrame = frame - 1;
                    Platform.runLater(() -> outputArea.setText(outputAreaText + "\n\tProcessed Frames: " + finalFrame));
                }
            }

            fos.flush();

            /*
             * Some video decoders will cache video data before they begin decoding, so
             * when you're done, you need to flush them.
             *
             * The convention to flush encoders/decoders in Humble Video is to keep
             * passing in null until incomplete samples or packets are returned.
             */
            do {
                decoder.decode(picture, null, 0);
            } while (picture.isComplete());
        } catch (final IOException e) {
            // todo Alert the user to this issue
            final Logger logger = LogManager.getLogger();
{'fraction_non_alphanumeric': 0.1, 'fraction_numerical': 0.0024890190336749633, 'mean_word_length': 2.2487514863258027, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '7527556', 'n_tokens_mistral': 3583, 'n_tokens_neox': 3406, 'n_words': 887}