Skip to content

Commit

Permalink
Bug fix for KinesisVideoClient.unregisterMediaSource() accessing to f…
Browse files Browse the repository at this point in the history
…reed native object issue.

Add KinesisVideoClient.freeMediaSource() clean-up function to handle async behavior.
  • Loading branch information
chehefen committed Feb 8, 2019
1 parent 9757746 commit a33af12
Show file tree
Hide file tree
Showing 2,095 changed files with 1,714 additions and 505 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ This should resolve native library loading issues.

## Release Notes

### Release 1.9.0 (08 Feburary 2019)
* Bug fix for KinesisVideoClient.unregisterMediaSource() accessing to freed native object issue.
* Add KinesisVideoClient.freeMediaSource() clean-up function to handle async behavior.

### Release 1.8.0 (25th January 2019)
* Fix duplicate stream error after unregistering media source when service call failed
* Fix inputstream not closing after stopSync issue
Expand Down
16 changes: 15 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<groupId>com.amazonaws</groupId>
<artifactId>amazon-kinesis-video-streams-producer-sdk-java</artifactId>
<name>Amazon Kinesis Video Streams Producer SDK Java</name>
<version>1.8.0</version>
<version>1.9.0</version>
<description>The Amazon Kinesis Video Streams Producer SDK for Java enables Java developers to ingest data into
Amazon Kinesis Video.
</description>
Expand All @@ -26,6 +26,20 @@
</repository>
</repositories>

<developers>
<developer>
<id>amazonwebservices</id>
<organization>Amazon Web Services</organization>
<organizationUrl>https://aws.amazon.com</organizationUrl>
<roles>
<role>developer</role>
</roles>
</developer>
</developers>
<url>https://aws.amazon.com/kinesis/video-streams</url>
<scm>
<url>https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-java.git</url>
</scm>
<licenses>
<license>
<name>Apache License Version 2.0</name>
Expand Down
34 changes: 31 additions & 3 deletions src/main/demo/com/amazonaws/kinesisvideo/demoapp/DemoAppMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,24 @@
import com.amazonaws.kinesisvideo.common.exception.KinesisVideoException;
import com.amazonaws.kinesisvideo.demoapp.auth.AuthHelper;
import com.amazonaws.kinesisvideo.java.client.KinesisVideoJavaClientFactory;
import com.amazonaws.kinesisvideo.java.mediasource.file.AudioVideoFileMediaSource;
import com.amazonaws.kinesisvideo.java.mediasource.file.AudioVideoFileMediaSourceConfiguration;
import com.amazonaws.kinesisvideo.java.mediasource.file.ImageFileMediaSource;
import com.amazonaws.kinesisvideo.java.mediasource.file.ImageFileMediaSourceConfiguration;
import com.amazonaws.regions.Regions;

import static com.amazonaws.kinesisvideo.util.StreamInfoConstants.ABSOLUTE_TIMECODES;

/**
* Demo Java Producer.
*/
public final class DemoAppMain {
// Use a different stream name when testing audio/video sample
private static final String STREAM_NAME = "my-stream";
private static final int FPS_25 = 25;
private static final int RETENTION_ONE_HOUR = 1;
private static final String IMAGE_DIR = "src/main/resources/data/h264/";
private static final String FRAME_DIR = "src/main/resources/data/audio-video-frames";
// CHECKSTYLE:SUPPRESS:LineLength
// Need to get key frame configured properly so the output can be decoded. h264 files can be decoded using gstreamer plugin
// gst-launch-1.0 rtspsrc location="YourRtspUri" short-header=TRUE protocols=tcp ! rtph264depay ! decodebin ! videorate ! videoscale ! vtenc_h264_hw allow-frame-reordering=FALSE max-keyframe-interval=25 bitrate=1024 realtime=TRUE ! video/x-h264,stream-format=avc,alignment=au,profile=baseline,width=640,height=480,framerate=1/25 ! multifilesink location=./frame-%03d.h264 index=1
Expand All @@ -37,13 +44,16 @@ public static void main(final String[] args) {

// create a media source. this class produces the data and pushes it into
// Kinesis Video Producer lower level components
final MediaSource bytesMediaSource = createImageFileMediaSource();
final MediaSource mediaSource = createImageFileMediaSource();

// Audio/Video sample is available for playback on HLS (Http Live Streaming)
//final MediaSource mediaSource = createFileMediaSource();

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

// start streaming
bytesMediaSource.start();
mediaSource.start();
} catch (final KinesisVideoException e) {
throw new RuntimeException(e);
}
Expand All @@ -68,4 +78,22 @@ private static MediaSource createImageFileMediaSource() {

return mediaSource;
}

/**
* Create a MediaSource based on local sample H.264 frames and AAC frames.
*
* @return a MediaSource backed by local H264 and AAC frame files
*/
private static MediaSource createFileMediaSource() {
final AudioVideoFileMediaSourceConfiguration configuration =
new AudioVideoFileMediaSourceConfiguration.AudioVideoBuilder()
.withDir(FRAME_DIR)
.withRetentionPeriodInHours(RETENTION_ONE_HOUR)
.withAbsoluteTimecode(ABSOLUTE_TIMECODES)
.build();
final AudioVideoFileMediaSource mediaSource = new AudioVideoFileMediaSource(STREAM_NAME);
mediaSource.configure(configuration);

return mediaSource;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.amazonaws.kinesisvideo.client;


import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.entity.ContentType;
import com.amazonaws.kinesisvideo.http.KinesisVideoApacheHttpClient;
import com.amazonaws.kinesisvideo.http.HttpMethodName;
import com.amazonaws.kinesisvideo.signing.KinesisVideoSigner;
import java.net.URI;

public final class GetInletMediaClient {
private static final String CONTENT_TYPE_HEADER_KEY = "Content-Type";
private static final String X_AMZN_REQUEST_ID = "x-amzn-RequestId";
private URI mUri;
private KinesisVideoSigner mSigner;
private String mGetInletMediaInputInJson;
private Integer mConnectionTimeoutInMillis;
private Integer mReadTimeoutInMillis;

public CloseableHttpResponse execute( final String requestId) {
if (requestId == null) {
throw new NullPointerException("requestId");
}
final KinesisVideoApacheHttpClient client = getHttpClient(requestId);
return client.executeRequest();
}

private KinesisVideoApacheHttpClient getHttpClient( final String requestId) {
if (requestId == null) {
throw new NullPointerException("requestId");
}
KinesisVideoApacheHttpClient.Builder clientBuilder = KinesisVideoApacheHttpClient.builder().withUri(mUri).withContentType(ContentType.APPLICATION_JSON).withMethod(HttpMethodName.POST).withContentInJson(mGetInletMediaInputInJson).withHeader(CONTENT_TYPE_HEADER_KEY, ContentType.APPLICATION_JSON.getMimeType()).withHeader(X_AMZN_REQUEST_ID, requestId);
if (mConnectionTimeoutInMillis != null) {
clientBuilder = clientBuilder.withConnectionTimeoutInMillis(mConnectionTimeoutInMillis.intValue());
}
if (mReadTimeoutInMillis != null) {
clientBuilder = clientBuilder.withSocketTimeoutInMillis(mReadTimeoutInMillis.intValue());
}
final KinesisVideoApacheHttpClient client = clientBuilder.build();
mSigner.sign(client);
return client;
}

GetInletMediaClient(final URI uri, final KinesisVideoSigner signer, final String getInletMediaInputInJson, final Integer connectionTimeoutInMillis, final Integer readTimeoutInMillis) {
this.mUri = uri;
this.mSigner = signer;
this.mGetInletMediaInputInJson = getInletMediaInputInJson;
this.mConnectionTimeoutInMillis = connectionTimeoutInMillis;
this.mReadTimeoutInMillis = readTimeoutInMillis;
}


public static class GetInletMediaClientBuilder {
private URI uri;
private KinesisVideoSigner signer;
private String getInletMediaInputInJson;
private Integer connectionTimeoutInMillis;
private Integer readTimeoutInMillis;

GetInletMediaClientBuilder() {
}

public GetInletMediaClientBuilder uri(final URI uri) {
this.uri = uri;
return this;
}

public GetInletMediaClientBuilder signer(final KinesisVideoSigner signer) {
this.signer = signer;
return this;
}

public GetInletMediaClientBuilder getInletMediaInputInJson(final String getInletMediaInputInJson) {
this.getInletMediaInputInJson = getInletMediaInputInJson;
return this;
}

public GetInletMediaClientBuilder connectionTimeoutInMillis(final Integer connectionTimeoutInMillis) {
this.connectionTimeoutInMillis = connectionTimeoutInMillis;
return this;
}

public GetInletMediaClientBuilder readTimeoutInMillis(final Integer readTimeoutInMillis) {
this.readTimeoutInMillis = readTimeoutInMillis;
return this;
}

public GetInletMediaClient build() {
return new GetInletMediaClient(uri, signer, getInletMediaInputInJson, connectionTimeoutInMillis, readTimeoutInMillis);
}

@Override
public String toString() {
return "GetInletMediaClient.GetInletMediaClientBuilder(uri=" + this.uri + ", signer=" + this.signer + ", getInletMediaInputInJson=" + this.getInletMediaInputInJson + ", connectionTimeoutInMillis=" + this.connectionTimeoutInMillis + ", readTimeoutInMillis=" + this.readTimeoutInMillis + ")";
}
}

public static GetInletMediaClientBuilder builder() {
return new GetInletMediaClientBuilder();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@
public interface KinesisVideoClient {
/**
* Returns whether the client has been initialized
*
* @return true if initialized. false otherwise.
*/
boolean isInitialized();

/**
* Initializes the client object.
*
* @param deviceInfo Device info for which the client needs to be initialized.
* @throws KinesisVideoException if unable to initialize KinesisVideoClient.
*/
void initialize(@Nonnull final DeviceInfo deviceInfo)
throws KinesisVideoException;
Expand All @@ -40,28 +45,42 @@ void initialize(@Nonnull final DeviceInfo deviceInfo)
/**
* Register a media source. The media source will be binding to kinesis video producer stream
* to send out data from media source.
* Sync call to create the stream and bind to media source.
*
* @param mediaSource media source binding to kinesis video producer stream
* @throws KinesisVideoException
* @throws KinesisVideoException if unable to register media source.
*/
void registerMediaSource(final MediaSource mediaSource) throws KinesisVideoException;

/**
* Un-Register a media source. The media source will stop binding to kinesis video producer stream
* and it cannot send data via producer stream afterwards until register again.
* Sync call and could be block for 15 seconds if error happens when stopping stream.
*
* @param mediaSource media source to stop binding to kinesis video producer stream
* @throws KinesisVideoException
* @throws KinesisVideoException if unable to unregister media source.
*/
void unregisterMediaSource(final MediaSource mediaSource) throws KinesisVideoException;

/**
* Start all registered media sources
*
* @throws KinesisVideoException if unable to start all media sources.
*/
void startAllMediaSources() throws KinesisVideoException;

/**
* Free a media source. Async call to clean up resources if error happens.
*
* @param mediaSource media source binding to kinesis video producer stream to be freed
* @throws KinesisVideoException if unable to free media source.
*/
void freeMediaSource(@Nonnull final MediaSource mediaSource) throws KinesisVideoException;

/**
* Stop all registered media sources
*
* @throws KinesisVideoException if unable to stop all media sources.
*/
void stopAllMediaSources() throws KinesisVideoException;

Expand All @@ -70,6 +89,7 @@ void initialize(@Nonnull final DeviceInfo deviceInfo)
* the media source type, create the instance, and ensure that it is configured with working
* parameters
*
* @param streamName Stream name for the media source
* @param mediaSourceConfiguration, configuration to create specific media source
* @return configured and working media source
* @throws UnsupportedConfigurationException is thrown when the configuration is not supported,
Expand All @@ -84,6 +104,8 @@ MediaSource createMediaSource(

/**
* Stops the media sources and frees/releases the underlying objects
*
* @throws KinesisVideoException if unable to free resources.
*/
void free() throws KinesisVideoException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,10 @@ public Builder logUsedBandwidth(final boolean logBandwidth) {
/**
* Allows writing the stream data into a localc file in addition to sending it to back-end.
* <p>
* Useful for debugging
* @param fileOutputPath Output file path
* @return Builder object
*
* NOTE: Useful for debugging
*/
public Builder fileOutputPath(final String fileOutputPath) {
mFileOutputPath = fileOutputPath;
Expand All @@ -297,9 +300,9 @@ public Builder log(final Log log) {
/**
* Add additional unsigned header. For testing use only.
*
* @param name
* @param value
* @return
* @param name Header key
* @param value Header value
* @return Builder object.
*/
public Builder unsignedHeader(final String name, final String value) {
if (unsignedHeaders == null) {
Expand Down

This file was deleted.

Loading

0 comments on commit a33af12

Please sign in to comment.