/* This file is part of JFLICKS. JFLICKS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. JFLICKS 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 General Public License for more details. You should have received a copy of the GNU General Public License along with JFLICKS. If not, see <http://www.gnu.org/licenses/>. */ package org.jflicks.tv.recorder; import java.io.File; import org.jflicks.job.AbstractJob; import org.jflicks.job.JobContainer; import org.jflicks.job.JobEvent; import org.jflicks.job.JobListener; import org.jflicks.job.JobManager; import org.jflicks.job.SystemJob; /** * Transfer a file using curl. * * @author Doug Barnum * @version 1.0 */ public class HlsJob extends AbstractJob implements JobListener { private SystemJob systemJob; private JobContainer jobContainer; private String input; private String output; private String videoCodec; private String audioCodec; private String optional; private File directory; private long duration; /** * Simple four argument constructor. * * @param input An input String. * @param output An output String. * @param directory A given File. * @param duration A given time in seconds. */ public HlsJob(String input, String output, File directory, long duration) { setInput(input); setOutput(output); setDirectory(directory); setDuration(duration); setVideoCodec("copy"); setAudioCodec("libfdk_aac"); setOptional(""); } /** * The local File to save the data. * * @return The File instance. */ public File getDirectory() { return (directory); } private void setDirectory(File f) { directory = f; } /** * The input String as a URL or path. * * @return The input String. */ public String getInput() { return (input); } private void setInput(String s) { input = s; } /** * The output String as a file prefix. * * @return The output String. */ public String getOutput() { return (output); } private void setOutput(String s) { output = s; } /** * The time in seconds to record from a HDHR. * * @return The time in seconds. */ public long getDuration() { return (duration); } private void setDuration(long l) { duration = l; } public String getVideoCodec() { return (videoCodec); } public void setVideoCodec(String s) { videoCodec = s; } public String getAudioCodec() { return (audioCodec); } public void setAudioCodec(String s) { audioCodec = s; } public String getOptional() { return (optional); } public void setOptional(String s) { optional = s; } private SystemJob getSystemJob() { return (systemJob); } private void setSystemJob(SystemJob j) { systemJob = j; } private JobContainer getJobContainer() { return (jobContainer); } private void setJobContainer(JobContainer j) { jobContainer = j; } private boolean isV4l2(String s) { boolean result = false; if (s != null) { result = s.startsWith("/dev/video"); } return (result); } /** * {@inheritDoc} */ public void start() { setTerminate(false); } /** * {@inheritDoc} */ public void run() { File f = getDirectory(); String inStr = getInput(); String outStr = getOutput(); if ((f != null) && (inStr != null) && (outStr != null)) { String prefix = ""; if (isV4l2(inStr)) { prefix = "-f v4l2"; } String command = "ffmpeg -i" + " " + prefix + " " + inStr + " -map 0:0 -map 0:1 -map 0:1 -c:v " + getVideoCodec() + " -c:a:0 " + getAudioCodec() + " -c:a:1 copy" + " " + getOptional() + " -f segment -segment_list" + " " + outStr + ".m3u8" + " -segment_time 10 -segment_list_flags +live" + " " + outStr + ".%06d.ts"; /* String command = "ffmpeg -i" + " " + prefix + " " + inStr + " -vcodec " + getVideoCodec() + " -acodec " + getAudioCodec() + " " + getOptional() + " -map 0 -f segment -segment_list" + " " + outStr + ".m3u8" + " -segment_time 10 -segment_list_flags +live" + " " + outStr + ".%06d.ts"; */ SystemJob job = SystemJob.getInstance(command, f); fireJobEvent(JobEvent.UPDATE, "command: <" + job.getCommand() + ">"); setSystemJob(job); job.addJobListener(this); JobContainer jc = JobManager.getJobContainer(job); setJobContainer(jc); jc.start(); long l = getDuration(); if (l == 0) { // This is just to record something...the duration was // not set so lets record for one minute. This should // not happen. l = 60 * 1000; } else { // Turn seconds into milliseconds. l *= 1000; } long now = System.currentTimeMillis(); l += now; long sleep = getSleepTime(); while (!isTerminate()) { JobManager.sleep(sleep); now = System.currentTimeMillis(); if (now >= l) { stop(); } else if ((now + 20000) > l) { // twenty second warning! sleep = 100; } } } fireJobEvent(JobEvent.COMPLETE); } /** * {@inheritDoc} */ public void stop() { setTerminate(true); JobContainer jc = getJobContainer(); SystemJob job = getSystemJob(); if ((jc != null) && (job != null)) { job.removeJobListener(this); jc.stop(); setJobContainer(null); setSystemJob(null); } } /** * {@inheritDoc} */ public void jobUpdate(JobEvent event) { if (event.getType() == JobEvent.COMPLETE) { setTerminate(true); } else if (event.getType() == JobEvent.UPDATE) { //fireJobEvent(JobEvent.UPDATE, event.getMessage()); } } public static void main(String[] args) { File dir = new File("/Users/djb/tmp/ggg"); HlsJob job = new HlsJob( "/Users/djb/tmp/EP014124480053_2013_11_13_01_00.ts", "EP014124480053_2013_11_13_01_00", dir, 60); final JobContainer jc = JobManager.getJobContainer(job); jc.start(); } }