//package org.aohe.webcam;
///*******************************************************************************
// * 版权所有 (c) 2014, Art Clarke. 保留所有权利。
// *
// * 本文件是Humble-Video的一部分。
// *
// * Humble-Video 是自由软件：您可以根据自由软件基金会发布的GNU Affero通用公共许可证的条款重新分发和/或修改它，
// * 许可证版本为3，或（由您选择）任何更新的版本。
// *
// * Humble-Video 按“原样”分发，没有任何形式的担保；甚至没有默示的适销性或特定用途适用性的保证。
// * 有关详细信息，请参阅GNU Affero通用公共许可证。
// *
// * 您应该已经收到了一份GNU Affero通用公共许可证的副本。如果没有，请参见<http://www.gnu.org/licenses/>。
// *******************************************************************************/
//import java.awt.*;
//import java.awt.image.BufferedImage;
//import java.io.IOException;
//import java.nio.ByteBuffer;
//
//import com.github.eduramiba.webcamcapture.drivers.NativeDriver;
//import com.github.sarxos.webcam.Webcam;
//import com.github.sarxos.webcam.WebcamResolution;
//import io.humble.ferry.Buffer;
//import org.aohe.constant.SocketEnum;
//import org.aohe.web.SocketUtils;
//import org.apache.commons.cli.CommandLine;
//import org.apache.commons.cli.CommandLineParser;
//import org.apache.commons.cli.HelpFormatter;
//import org.apache.commons.cli.OptionBuilder;
//import org.apache.commons.cli.Options;
//import org.apache.commons.cli.ParseException;
//
//import io.humble.video.Codec;
//import io.humble.video.Encoder;
//import io.humble.video.MediaAudio;
//import io.humble.video.MediaPacket;
//import io.humble.video.MediaPicture;
//import io.humble.video.Muxer;
//import io.humble.video.MuxerFormat;
//import io.humble.video.PixelFormat;
//import io.humble.video.Rational;
//import io.humble.video.awt.MediaPictureConverter;
//import io.humble.video.awt.MediaPictureConverterFactory;
//
///**
// * 将计算机屏幕内容录制到媒体文件中，持续指定的时间。
// * 这是一个演示程序，旨在教授如何使用Humble API。
// * <p>
// * 引入的概念：
// * </p>
// * <ul>
// * <li>Muxer: {@link Muxer} 对象是可以写入媒体数据的容器。</li>
// * <li>编码器: {@link Encoder} 对象可以将 {@link MediaAudio} 或 {@link MediaPicture} 对象转换为 {@link MediaPacket} 对象，
// * 以便将其写入 {@link Muxer} 对象。</li>
// * </ul>
// *
// * <p>
// * 使用Maven运行此程序：
// * </p>
// * <pre>
// * mvn install exec:java -Dexec.mainClass="io.humble.video.demos.RecordAndEncodeVideo" -Dexec.args="filename.mp4"
// * </pre>
// *
// * @author aclarke
// *
// */
//public class RecordAndEncodeVideo {
//
//    /**
//     * 录制屏幕内容。
//     *
//     * @param filename 文件名，用于保存录制的视频。
//     * @param formatName 视频格式名称，如果未指定则根据文件名猜测。
//     * @param codecName 编解码器名称，如果未指定则根据格式猜测。
//     * @param duration 录制的持续时间（秒）。
//     * @throws AWTException 如果创建Robot对象失败。
//     * @throws InterruptedException 如果线程被中断。
//     * @throws IOException 如果发生I/O错误。
//     */
//    private static void recordScreen(String filename, String formatName,
//                                     String codecName, int duration) throws AWTException, InterruptedException, IOException {
//        SocketUtils.start(SocketEnum.CAM_SOCKET);
//        Webcam.setDriver(new NativeDriver());
//        Webcam webcam = Webcam.getDefault();
//        Dimension[] viewSizes = webcam.getViewSizes();
//        Dimension bigSize = WebcamResolution.VGA.getSize();
//        for (Dimension d : viewSizes){
//            //获取最大分辨率
//            if(bigSize.getWidth()<d.getWidth()){
//                bigSize = d;
//            }
//        }
//        webcam.setViewSize(bigSize);
//        webcam.open();
//
//        final Rational framerate = Rational.make(1, 10);
//
//        /** 创建muxer，使用传递的文件名和格式名称（如果有）。 */
//        final Muxer muxer = Muxer.make(filename, null, formatName);
//
//        /** 决定要使用的编解码器类型。muxer只能使用有限的编解码器集。我们将选择第一个可用的编解码器，
//         * 或者如果用户提供了编解码器名称，则强制使用该编解码器。
//         */
//        final MuxerFormat format = muxer.getFormat();
//        final Codec codec;
//        if (codecName != null) {
//            codec = Codec.findEncodingCodecByName(codecName);
//        } else {
//            codec = Codec.findEncodingCodec(Codec.ID.CODEC_ID_H264);
//        }
//
//        /**
//         * 现在我们知道要使用的编解码器，需要创建一个编码器。
//         */
//        Encoder encoder = Encoder.make(codec);
//
//        /**
//         * 视频编码器至少需要知道以下信息：
//         *   宽度
//         *   高度
//         *   像素格式
//         * 某些编码器还需要知道帧率（旧的编码器可能有固定的帧率）。这里我们保持简单。
//         */
//        encoder.setWidth(bigSize.width);
//        encoder.setHeight(bigSize.height);
//        // 我们将使用420P格式，因为这是大多数现代视频格式所使用的。
//        final PixelFormat.Type pixelformat = PixelFormat.Type.PIX_FMT_YUV420P;
//        encoder.setPixelFormat(pixelformat);
//        encoder.setTimeBase(framerate);
//
//        /** 某些格式需要全局（而不是每流）头文件，因此需要告知编码器。由于编码器与复用器分离，
//         * 没有简单的方法来确定这一点。
//         */
//        if (format.getFlag(MuxerFormat.Flag.GLOBAL_HEADER))
//            encoder.setFlag(Encoder.Flag.FLAG_GLOBAL_HEADER, true);
//
//        /** 打开编码器。 */
//        encoder.open(null, null);
//
//        /** 将此流添加到复用器。 */
//        muxer.addNewStream(encoder);
//
//        /** 打开复用器以开始工作。 */
//        muxer.open(null, null);
//
//        /** 确保我们有正确的MediaPicture格式对象来编码数据。
//         * Java（以及大多数屏幕图形程序）使用某种变体的RGB图像编码。大多数视频编解码器使用某种变体的YCrCb格式。
//         * 因此我们需要进行转换。为此，稍后我们将引入一个MediaPictureConverter对象。
//         */
//        MediaPictureConverter converter = null;
//        final MediaPicture picture = MediaPicture.make(
//                encoder.getWidth(),
//                encoder.getHeight(),
//                pixelformat);
//        picture.setTimeBase(framerate);
//
//        /** 开始主循环，抓取屏幕快照并编码，然后写入结果包。 */
//        final MediaPacket packet = MediaPacket.make();
//        for (int i = 0; i < duration / framerate.getDouble(); i++) {
//            /** 抓取屏幕并转换图像为TYPE_3BYTE_BGR */
//            final BufferedImage screen = convertToType(webcam.getImage(), BufferedImage.TYPE_3BYTE_BGR);
//
//            /** 图像很可能不是YUV420P格式，因此我们将使用一些实用工具进行转换。 */
//            if (converter == null)
//                converter = MediaPictureConverterFactory.createConverter(screen, picture);
//            converter.toPicture(picture, screen, i);
//
//            do {
//                encoder.encode(packet, picture);
//                if (packet.isComplete()){
//                    Buffer data = packet.getData();
//                        SocketUtils.get(SocketEnum.CAM_SOCKET.getName())
//                                .broadcast(data.getByteBuffer(0, data.getBufferSize()));
//                    muxer.write(packet, false);
//                }
//            } while (packet.isComplete());
//
//            /** 睡眠直到下一次抓取快照的时间。 */
//            Thread.sleep((long) (1000 * framerate.getDouble()));
//        }
//
//        /** 编码器有时会缓存图片以进行关键帧优化，因此需要刷新。与解码器一样，约定是传递null输入直到输出不完整。 */
//        do {
//            encoder.encode(packet, null);
//            if (packet.isComplete())
//                muxer.write(packet, false);
//        } while (packet.isComplete());
//
//        /** 最后，清理资源。 */
//        muxer.close();
//    }
//
//    @SuppressWarnings("static-access")
//    public static void main(String[] args) throws InterruptedException, IOException, AWTException
//    {
//        final Options options = new Options();
//        options.addOption("h", "help", false, "显示帮助");
//        options.addOption("v", "version", false, "显示库版本");
//        options.addOption(OptionBuilder.withArgName("format")
//                .withLongOpt("format")
//                .hasArg().
//                withDescription("要使用的复用器格式。如果未指定，将根据文件名猜测")
//                .create("f"));
//        options.addOption(OptionBuilder.withArgName("codec")
//                .withLongOpt("codec")
//                .hasArg()
//                .withDescription("编码视频时使用的编解码器；如果未指定，将根据格式猜测")
//                .create("c"));
//        options.addOption(OptionBuilder.withArgName("duration")
//                .withLongOpt("duration")
//                .hasArg()
//                .withDescription("要录制的屏幕截图秒数，默认为10秒")
//                .create("d"));
//        options.addOption(OptionBuilder.withArgName("snaps per second")
//                .withLongOpt("snaps")
//                .hasArg()
//                .withDescription("每秒抓取的图片数量（即帧率），默认为5")
//                .create("s"));
//
//        final CommandLineParser parser = new org.apache.commons.cli.BasicParser();
//        try {
//            final CommandLine cmd = parser.parse(options, args);
//            final String[] parsedArgs = cmd.getArgs();
//            if (cmd.hasOption("version")) {
//                // 查找正在运行的库版本
//                final String version = io.humble.video_native.Version.getVersionInfo();
//                System.out.println("Humble 版本: " + version);
//            } else if (cmd.hasOption("help") || parsedArgs.length != 1) {
//                final HelpFormatter formatter = new HelpFormatter();
//                formatter.printHelp(RecordAndEncodeVideo.class.getCanonicalName() + " <filename>", options);
//            } else {
//                /**
//                 * 读取选项值及其默认值。
//                 */
//                final int duration = Integer.parseInt(cmd.getOptionValue("duration", "10"));
//                if (duration <= 0)
//                    throw new IllegalArgumentException("duration 必须大于 0");
//                final int snaps = Integer.parseInt(cmd.getOptionValue("snaps", "5"));
//                if (snaps <= 0)
//                    throw new IllegalArgumentException("snaps 必须大于 0");
//                final String codecname = cmd.getOptionValue("codec");
//                final String formatname = cmd.getOptionValue("format");
//                final String filename = cmd.getArgs()[0];
//
//                recordScreen(filename, formatname, codecname, 1000);
//            }
//        } catch (ParseException e) {
//            System.err.println("解析命令行时出现异常: " + e.getLocalizedMessage());
//        }
//    }
//
//    /**
//     * 将任意类型的 {@link BufferedImage} 转换为指定类型的 {@link BufferedImage}。
//     * 如果源图像已经是目标类型，则返回源图像，否则创建新图像并将源图像的内容复制到新图像中。
//     *
//     * @param sourceImage 要转换的图像。
//     * @param targetType 目标 BufferedImage 类型。
//     * @return 指定目标类型的 BufferedImage。
//     * @see BufferedImage
//     */
//    public static BufferedImage convertToType(BufferedImage sourceImage,
//                                              int targetType) {
//        BufferedImage image;
//
//        // 如果源图像是目标类型，则返回源图像
//        if (sourceImage.getType() == targetType)
//            image = sourceImage;
//
//            // 否则创建目标类型的新图像并绘制新图像
//        else {
//            image = new BufferedImage(sourceImage.getWidth(),
//                    sourceImage.getHeight(), targetType);
//            image.getGraphics().drawImage(sourceImage, 0, 0, null);
//        }
//
//        return image;
//    }
//}
