Skip to content

Commit

Permalink
Release 1.5.0 (24th August 2018)
Browse files Browse the repository at this point in the history
Windows native library available for Producer SDK
Intermittent producer support
Per-stream customized callback support
  • Loading branch information
chehefen committed Aug 31, 2018
1 parent 3ce60ec commit 1c227ef
Show file tree
Hide file tree
Showing 105 changed files with 524 additions and 435 deletions.
40 changes: 15 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ The Amazon Kinesis Video Streams Producer SDK Java makes it easy to build an on-

### Prerequisites

* You can find available pre-built KinesisVideoProducerJNI library in [src/main/resources/lib/](https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-java/tree/master/src/main/resources/lib) for Mac (x64), Ubuntu (x64) and Raspian (x86). If pre-built libraries did not work for you, ["KinesisVideoProducerJNI"](https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-cpp) native library needs to be built first before running the Java demo application. Please follow the steps in the section **Build the native library (KinesisVideoProducerJNI) to run Java Demo App** in Producer SDK CPP [readme](https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-cpp).
* You can find available pre-built KinesisVideoProducerJNI library in [src/main/resources/lib/](https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-java/tree/master/src/main/resources/lib) for Mac (x64), Ubuntu (x64) and Raspian (x86) and Windows 10. If pre-built libraries did not work for you, ["KinesisVideoProducerJNI"](https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-cpp) native library needs to be built first before running the Java demo application. Please follow the steps in the section **Build the native library (KinesisVideoProducerJNI) to run Java Demo App** in Producer SDK CPP [readme](https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-cpp).

### Building from Source

Expand All @@ -31,12 +31,12 @@ Import the Maven project to your IDE, it will find dependency packages from Mave

Run `DemoAppMain.java` in `./src/main/demo` with JVM arguments set to
```
-Daws.accessKeyId={YourAwsAccessKey} -Daws.secretKey={YourAwsSecretKey} -Djava.library.path={NativeLibraryPath}
-Daws.accessKeyId=<YourAwsAccessKey> -Daws.secretKey=<YourAwsSecretKey> -Djava.library.path=<NativeLibraryPath>
```
for **non-temporary** AWS credential.

```
-Daws.accessKeyId={YourAwsAccessKey} -Daws.secretKey={YourAwsSecretKey} -Daws.sessionToken={YourAwsSessionToken} -Djava.library.path={NativeLibraryPath}
-Daws.accessKeyId=<YourAwsAccessKey> -Daws.secretKey=<YourAwsSecretKey> -Daws.sessionToken=<YourAwsSessionToken> -Djava.library.path=<NativeLibraryPath>
```
for *temporary* AWS credential.

Expand All @@ -45,43 +45,28 @@ for *temporary* AWS credential.
* `libKinesisVideoProducerJNI.dylib` for Mac OS
* `KinesisVideoProducerJNI.dll` for Windows

If you are using pre-built libraries, please specify the path of library. Take pre-build library for Mac as example, you can specify `src/resources/lib/mac` as {NativeLibraryPath}.
If you are using pre-built libraries, please specify the path of library. Take pre-build library for Mac as example, you can specify `src/resources/lib/mac` as <NativeLibraryPath>.

Demo app will start running and putting sample video frames in a loop into Kinesis Video Streams. You can change your stream settings in `DemoAppMain.java` before you run the app.

##### Run the demo application from command line

If you want to run the `DemoAppMain`, follow the [steps](https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-java/issues/14) below.
If you want to run the `DemoAppMain`, follow the [steps](https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-java/issues/14) below. See [Prerequisites](https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-java#prerequisites) to find available native library needed to run `DemoAppMain`.

Change the current working directory to

```
$ cd /<YOUR_FOLDER_PATH_WHERE_SDK_IS_DOWNLOADED>/amazon-kinesis-video-streams-producer-sdk-java/
```

Compile the Java SDK and Demoapp
```
$ mvn package
Compile and assemble Java SDK, Java Demoapp and the Maven dependencies
```
Create a temporary filename in /tmp directory
$ mvn clean compile assembly:single
```
$ jar_files=$(mktemp)
```
Create classpath string of dependencies from the local repository to a file

```
$ mvn -Dmdep.outputFile=$jar_files dependency:build-classpath
```
Set the **LD_LIBRARY_PATH** to include the open source dependencies.

(refer: [Kinesis Video Streams Producer SDK CPP](https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-cpp)
```
$ export LD_LIBRARY_PATH=/<YOUR_FOLDER_PATH_WHERE_SDK_IS_DOWNLOADED>/amazon-kinesis-video-streams-producer-sdk-cpp/kinesis-video-native-build/downloads/local/lib:$LD_LIBRARY_PATH
$ classpath_values=$(cat $jar_files)
```
Start the demo app
```
$ java -classpath target/kinesisvideo-java-demo-1.0-SNAPSHOT.jar:$classpath_values -Daws.accessKeyId=${ACCESS_KEY} -Daws.secretKey=${SECRET_KEY} -Djava.library.path=/opt/amazon-kinesis-video-streams-producer-sdk-cpp/kinesis-video-native-build com.amazonaws.kinesisvideo.demoapp.DemoAppMain
$ java -classpath target/kinesisvideo-java-demo-1.0-SNAPSHOT-jar-with-dependencies.jar -Daws.accessKeyId=<ACCESS_KEY> -Daws.secretKey=<SECRET_KEY> -Djava.library.path=<NativeLibraryPath> com.amazonaws.kinesisvideo.demoapp.DemoAppMain
```

Expand All @@ -94,12 +79,12 @@ Refer the **README.md** file in the *dockerscripts* folder for running the buil
Run `PutMediaDemo.java` to send sample mkv stream to Kinesis Video Streams. **Note:** ACCESS_KEY and SECRET_KEY are required for running this sample application as well. However, this demo application does not require JNI.

```
-Daws.accessKeyId={YourAwsAccessKey} -Daws.secretKey={YourAwsSecretKey}
-Daws.accessKeyId=<YourAwsAccessKey> -Daws.secretKey=<YourAwsSecretKey>
```
for **non-temporary** AWS credential.

```
-Daws.accessKeyId={YourAwsAccessKey} -Daws.secretKey={YourAwsSecretKey} -Daws.sessionToken={YourAwsSessionToken}
-Daws.accessKeyId=<YourAwsAccessKey> -Daws.secretKey=<YourAwsSecretKey> -Daws.sessionToken=<YourAwsSessionToken>
```
#### Pre-built KinesisVideoProducerJNI library supported platforms
* Mac OS X (El capitan 10.11 or above)
Expand Down Expand Up @@ -148,6 +133,11 @@ This should resolve native library loading issues.

## Release Notes

### Release 1.5.0 (24th August 2018)
* Windows native library available for Producer SDK
* Intermittent producer support
* Per-stream customized callback support

### Release 1.3.1 (23rd July 2018)

* Add reset connection function.
Expand Down
13 changes: 13 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,19 @@
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.amazonaws.kinesisvideo.demoapp.DemoAppMain</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
</project>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public static void main(final String[] args) {
final MediaSource bytesMediaSource = createImageFileMediaSource();

// register media source with Kinesis Video Client
kinesisVideoClient.registerMediaSource(STREAM_NAME, bytesMediaSource);
kinesisVideoClient.registerMediaSource(bytesMediaSource);

// start streaming
bytesMediaSource.start();
Expand All @@ -63,7 +63,7 @@ private static MediaSource createImageFileMediaSource() {
.startFileIndex(START_FILE_INDEX)
.endFileIndex(END_FILE_INDEX)
.build();
final ImageFileMediaSource mediaSource = new ImageFileMediaSource();
final ImageFileMediaSource mediaSource = new ImageFileMediaSource(STREAM_NAME);
mediaSource.configure(configuration);

return mediaSource;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public abstract class AbstractKinesisVideoClient implements KinesisVideoClient {
/**
* Stores the list of streams
*/
private final List<MediaSource> mMediaSources = new ArrayList<MediaSource>();
protected final List<MediaSource> mMediaSources = new ArrayList<MediaSource>();

/**
* Whether the object has been initialized
Expand Down Expand Up @@ -121,9 +121,16 @@ public void free() throws KinesisVideoException {
* Adds an already created {@link MediaSource} to the list.
*/
@Override
public void registerMediaSource(@Nonnull final String streamName,
@Nonnull final MediaSource mediaSource) throws KinesisVideoException {
public void registerMediaSource(@Nonnull final MediaSource mediaSource) throws KinesisVideoException {
// The actual media source creation happens in the derived class
mMediaSources.add(mediaSource);
}

/**
* Removes/unregisters {@link MediaSource} from the list.
*/
@Override
public void unregisterMediaSource(@Nonnull final MediaSource mediaSource) throws KinesisVideoException {
mMediaSources.remove(mediaSource);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ void initialize(@Nonnull final DeviceInfo deviceInfo)
/**
* Register a media source
*/
void registerMediaSource(final String streamName, final MediaSource mediaSource) throws KinesisVideoException;
void registerMediaSource(final MediaSource mediaSource) throws KinesisVideoException;

/**
* Un-Register a media source
*/
void unregisterMediaSource(final MediaSource mediaSource) throws KinesisVideoException;

/**
* Start all registered media sources
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

import static com.amazonaws.kinesisvideo.common.preconditions.Preconditions.checkNotNull;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;

import javax.annotation.Nonnull;
Expand All @@ -15,6 +16,7 @@
import com.amazonaws.kinesisvideo.common.exception.KinesisVideoException;
import com.amazonaws.kinesisvideo.common.logging.Log;
import com.amazonaws.kinesisvideo.common.logging.LogLevel;
import com.amazonaws.kinesisvideo.common.preconditions.Preconditions;
import com.amazonaws.kinesisvideo.mediasource.ProducerStreamSink;
import com.amazonaws.kinesisvideo.producer.AuthCallbacks;
import com.amazonaws.kinesisvideo.producer.DeviceInfo;
Expand Down Expand Up @@ -48,14 +50,18 @@ public class NativeKinesisVideoClient extends AbstractKinesisVideoClient {
*/
private static final String TAG = "NativeKinesisVideoClient";

/**
* Map of the media source to KVS producer stream
*/
private final Map<MediaSource, KinesisVideoProducerStream> mMediaSourceToStreamMap;

/**
* Kinesis Video producer callbacks
*/
private final AuthCallbacks authCallbacks;
private final StorageCallbacks storageCallbacks;
private final StreamCallbacks streamCallbacks;
private final ServiceCallbacks defaultServiceCallbacks;
private final List<MediaSource> mediaSources;
private final AuthCallbacks mAuthCallbacks;
private final StorageCallbacks mStorageCallbacks;
private final StreamCallbacks mStreamCallbacks;
private final ServiceCallbacks mServiceCallbacks;

/**
* Underlying Kinesis Video producer object.
Expand Down Expand Up @@ -95,12 +101,12 @@ public NativeKinesisVideoClient(

super(log);

this.authCallbacks = checkNotNull(authCallbacks);
this.storageCallbacks = checkNotNull(storageCallbacks);
defaultServiceCallbacks = checkNotNull(serviceCallbacks);
this.streamCallbacks = checkNotNull(streamCallbacks);
mAuthCallbacks = checkNotNull(authCallbacks);
mStorageCallbacks = checkNotNull(storageCallbacks);
mServiceCallbacks = checkNotNull(serviceCallbacks);
mStreamCallbacks = checkNotNull(streamCallbacks);

mediaSources = new ArrayList<MediaSource>();
mMediaSourceToStreamMap = new HashMap<MediaSource, KinesisVideoProducerStream>();
}

/**
Expand All @@ -113,17 +119,41 @@ public void initialize(@Nonnull final DeviceInfo deviceInfo) throws KinesisVideo
}

@Override
public void registerMediaSource(final String streamName,
final MediaSource mediaSource) throws KinesisVideoException {
final KinesisVideoProducerStream producerStream = kinesisVideoProducer.createStreamSync(mediaSource.getStreamInfo(streamName), streamCallbacks);
mediaSources.add(mediaSource);
public void registerMediaSource(final MediaSource mediaSource) throws KinesisVideoException {
Preconditions.checkNotNull(mediaSource);
StreamCallbacks streamCallbacks = mediaSource.getStreamCallbacks();
if (streamCallbacks == null) {
streamCallbacks = mStreamCallbacks;
}

final KinesisVideoProducerStream producerStream = kinesisVideoProducer.createStreamSync(mediaSource.getStreamInfo(), streamCallbacks);
mediaSource.initialize(new ProducerStreamSink(producerStream));
defaultServiceCallbacks.addStream(producerStream);
mServiceCallbacks.addStream(producerStream);
mMediaSourceToStreamMap.put(mediaSource, producerStream);
super.registerMediaSource(mediaSource);
}

@Override
public void unregisterMediaSource(final MediaSource mediaSource) throws KinesisVideoException {
Preconditions.checkNotNull(mediaSource);
super.unregisterMediaSource(mediaSource);

final KinesisVideoProducerStream producerStream = mMediaSourceToStreamMap.get(mediaSource);

// The following call will not block for the stopped event
producerStream.stopStream();

kinesisVideoProducer.freeStream(producerStream);
mServiceCallbacks.removeStream(producerStream);
}

@Override
public void stopAllMediaSources() throws KinesisVideoException {
super.stopAllMediaSources();
for (final MediaSource mediaSource : mMediaSources) {
final KinesisVideoProducerStream producerStream = mMediaSourceToStreamMap.get(mediaSource);
producerStream.stopStreamSync();
}
}

@Override
Expand All @@ -144,7 +174,7 @@ public void free() throws KinesisVideoException {
if (isInitialized()) {
super.free();

defaultServiceCallbacks.free();
mServiceCallbacks.free();
kinesisVideoProducer.stopStreams();
kinesisVideoProducer.free();

Expand All @@ -159,9 +189,9 @@ public void free() throws KinesisVideoException {
@Nonnull
KinesisVideoProducer initializeNewKinesisVideoProducer(final DeviceInfo deviceInfo) throws ProducerException {
final KinesisVideoProducer kinesisVideoProducer = new NativeKinesisVideoProducerJni(
authCallbacks,
storageCallbacks,
defaultServiceCallbacks,
mAuthCallbacks,
mStorageCallbacks,
mServiceCallbacks,
mLog);
kinesisVideoProducer.createSync(deviceInfo);
return kinesisVideoProducer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.amazonaws.kinesisvideo.stream.throttling.BandwidthThrottler;
import com.amazonaws.kinesisvideo.stream.throttling.BandwidthThrottlerImpl;
import com.amazonaws.kinesisvideo.stream.throttling.OpsPerSecondMeasurer;
import com.amazonaws.kinesisvideo.util.VersionUtil;

import static com.amazonaws.kinesisvideo.common.preconditions.Preconditions.checkNotNull;
import static com.amazonaws.kinesisvideo.http.HttpMethodName.POST;
Expand All @@ -36,6 +37,7 @@ public final class PutMediaClient {
private static final String CHUNKED = "chunked";
private static final String CONNECTION = "connection";
private static final String KEEP_ALIVE = "keep-alive";
private static final String USER_AGENT = "user-agent";
private static final int BUFFER_SIZE = 128 * 128; //16kb
private static final double MILLI_TO_SEC = 1000;
private static final int LOGGING_INTERVAL = 250; // Rougly every 10 seconds in 25 fps
Expand Down Expand Up @@ -66,9 +68,10 @@ private void putMediaWithSender(final Consumer<OutputStream> sender) {
.log(log)
.header(STREAM_NAME_HEADER, mBuilder.mStreamName)
.header(TRANSFER_ENCODING, CHUNKED)
.header(CONNECTION, KEEP_ALIVE);
.header(CONNECTION, KEEP_ALIVE)
.header(USER_AGENT, VersionUtil.getUserAgent());
clientBuilder.setReceiverCallback(mBuilder.mAcksReceiver);
clientBuilder.header(PRODUCER_START_TIMESTAMP_HEADER,
clientBuilder.header(PRODUCER_START_TIMESTAMP_HEADER,
String.format(Locale.US, "%.3f", mBuilder.mTimestamp / MILLI_TO_SEC));
clientBuilder.header(FRAGMENT_TIME_CODE_TYPE_HEADER, mBuilder.mFragmentTimecodeType);
clientBuilder.completionCallback(mBuilder.mCompletion);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.amazonaws.kinesisvideo.client.mediasource;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import com.amazonaws.kinesisvideo.common.exception.KinesisVideoException;
import com.amazonaws.kinesisvideo.producer.StreamCallbacks;
import com.amazonaws.kinesisvideo.producer.StreamInfo;

/**
Expand All @@ -22,7 +24,7 @@ public interface MediaSource {
/**
* Returns the {@link StreamInfo} describing the stream this media source produces
*/
StreamInfo getStreamInfo(String streamName) throws KinesisVideoException;;
StreamInfo getStreamInfo() throws KinesisVideoException;;

/**
* Initializes the media source with a {@link MediaSourceSink} object
Expand Down Expand Up @@ -54,5 +56,14 @@ public interface MediaSource {
*/
void free() throws KinesisVideoException;

/**
* Returns the {@link MediaSourceSink} object
*/
MediaSourceSink getMediaSourceSink();

/**
* Returns a stream-specific {@link StreamCallbacks} implementation if any.
*/
@Nullable
StreamCallbacks getStreamCallbacks();
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,8 @@ public interface MediaSourceSink {

void onCodecPrivateData(final @Nullable byte[] codecPrivateData) throws KinesisVideoException;

void onFragmentMetadata(final @Nonnull String metadataName, final @Nonnull String metadataValue, final boolean persistent)
throws KinesisVideoException;

KinesisVideoProducerStream getProducerStream();
}
Loading

0 comments on commit 1c227ef

Please sign in to comment.