package com.qiniu.pili;
import com.google.gson.Gson;
import com.qiniu.pili.utils.UrlSafeBase64;
import java.io.UnsupportedEncodingException;
public final class Stream {
private StreamInfo info;
private String baseUrl;
private RPC cli;
private Gson gson;
private Stream() {
}
Stream(StreamInfo info, RPC cli) throws UnsupportedEncodingException {
this.info = info;
String ekey = UrlSafeBase64.encodeToString(info.getKey());
this.baseUrl = String.format("%s%s/v2/hubs/%s/streams/%s", Config.APIHTTPScheme, Config.APIHost, info.getHub(), ekey);
this.cli = cli;
this.gson = new Gson();
}
public String getHub() {
return info.getHub();
}
public long getDisabledTill() {
return info.getDisabledTill();
}
public String[] getConverts() {
return info.getConverts();
}
public String getKey() {
return info.getKey();
}
private void setDisabledTill(long disabledTill) throws PiliException {
DisabledArgs args = new DisabledArgs(disabledTill);
String path = baseUrl + "/disabled";
String json = gson.toJson(args);
try {
cli.callWithJson(path, json);
} catch (PiliException e) {
throw e;
} catch (Exception e) {
throw new PiliException(e);
}
}
private String appendQuery(String path, long start, long end) {
String flag = "?";
if (start > 0) {
path += String.format("%sstart=%d", flag, start);
flag = "&";
}
if (end > 0) {
path += String.format("%send=%d", flag, end);
}
return path;
}
public String toJson() {
return gson.toJson(info);
}
/**
* fetch stream info
*
* @return
* @throws PiliException
*/
public Stream info() throws PiliException {
try {
String resp = cli.callWithGet(baseUrl);
StreamInfo ret = gson.fromJson(resp, StreamInfo.class);
ret.setMeta(info.getHub(), info.getKey());
this.info = ret;
return this;
} catch (PiliException e) {
throw e;
} catch (Exception e) {
throw new PiliException(e);
}
}
/**
* diable stream
*
* @throws PiliException
*/
public void disable() throws PiliException {
setDisabledTill(-1);
}
/**
* disable stream
*
* @param disabledTill
* @throws PiliException
*/
public void disable(long disabledTill) throws PiliException {
setDisabledTill(disabledTill);
}
/**
* enable stream
*
* @throws PiliException
*/
public void enable() throws PiliException {
setDisabledTill(0);
}
/**
* get the status of live stream
*
* @return
* @throws PiliException
*/
public LiveStatus liveStatus() throws PiliException {
String path = baseUrl + "/live";
try {
String resp = cli.callWithGet(path);
LiveStatus status = gson.fromJson(resp, LiveStatus.class);
return status;
} catch (PiliException e) {
throw e;
} catch (Exception e) {
throw new PiliException(e);
}
}
/**
* save playback
*
* @param start
* @param end
* @return
* @throws PiliException
*/
public String save(long start, long end) throws PiliException {
SaveOptions args = new SaveOptions(start, end);
return save(args);
}
/**
* save playback with more options
*
* @param opts
* @return
* @throws PiliException
*/
public String save(SaveOptions opts) throws PiliException {
String path = baseUrl + "/saveas";
String json = gson.toJson(opts);
try {
String resp = cli.callWithJson(path, json);
SaveRet ret = gson.fromJson(resp, SaveRet.class);
return ret.fname;
} catch (PiliException e) {
throw e;
} catch (Exception e) {
throw new PiliException(e);
}
}
/**
* snapshot the live stream
*
* @param opts
* @return
* @throws PiliException
*/
public String snapshot(SnapshotOptions opts) throws PiliException {
String path = baseUrl + "/snapshot";
String json = gson.toJson(opts);
try {
String resp = cli.callWithJson(path, json);
SnapshotRet ret = gson.fromJson(resp, SnapshotRet.class);
return ret.fname;
} catch (PiliException e) {
throw e;
} catch (Exception e) {
throw new PiliException(e);
}
}
/**
* update convert configs
*
* @param profiles
* @throws PiliException
*/
public void updateConverts(String[] profiles) throws PiliException {
String path = baseUrl + "/converts";
String json = gson.toJson(new ConvertsOptions(profiles));
try {
cli.callWithJson(path, json);
} catch (PiliException e) {
throw e;
} catch (Exception e) {
throw new PiliException(e);
}
}
/**
* query the stream history
*
* @param start
* @param end
* @return
* @throws PiliException
*/
public Record[] historyRecord(long start, long end) throws PiliException {
String path = appendQuery(baseUrl + "/historyrecord", start, end);
try {
String resp = cli.callWithGet(path);
HistoryRet ret = gson.fromJson(resp, HistoryRet.class);
return ret.items;
} catch (PiliException e) {
throw e;
} catch (Exception e) {
throw new PiliException(e);
}
}
private class DisabledArgs {
long disabledTill;
public DisabledArgs(long disabledTill) {
this.disabledTill = disabledTill;
}
}
/*
LiveStatus
*/
public class FPSStatus {
public int audio;
public int video;
public int data;
}
public static class LiveStatus {
public long startAt;
public String clientIP;
public int bps;
public FPSStatus fps;
public String toJson() {
return new Gson().toJson(this);
}
}
public static class SaveOptions {
/**
* start unix time
*/
public long start;
/**
* end unix time. 0 means current time
*/
public long end;
/**
* the saved file name
*/
public String fname;
/**
* file format. default in m3u8
*/
public String format;
/**
* if qiniu dora pipeline is needed, assign this value
*/
public String pipeline;
/**
* URL address. After dora asynchronous operation is done, will notify this address
*/
public String notify;
/**
* ts's expiration days
* -1 means no change of ts's expiration
* 0 means storing forever
* any other positive number can change the ts's expiration days
*/
public long expireDays;
public SaveOptions() {
}
public SaveOptions(long start, long end) {
this.start = start;
this.end = end;
}
}
private class SaveRet {
String fname;
}
public static class SnapshotOptions {
/**
* the saved file name
*/
public String fname;
/**
* the unix time of snapshot. 0 means the current time
*/
public long time;
/**
* file format. default in jpg
*/
public String format;
public SnapshotOptions() {
}
public SnapshotOptions(String fname, long time, String format) {
this.fname = fname;
this.time = time;
this.format = format;
}
}
private class SnapshotRet {
String fname;
}
private class ConvertsOptions {
String[] converts;
public ConvertsOptions(String[] converts) {
this.converts = converts;
}
}
/*
history
*/
public class Record {
public long start;
public long end;
}
private class HistoryRet {
Record[] items;
}
}