Skip to content

Commit 1b2019d

Browse files
Merge pull request #109 from MixMasterMitch/cluster-packing
v1.0.15
2 parents 02d2011 + d3ad304 commit 1b2019d

File tree

15 files changed

+380
-179
lines changed

15 files changed

+380
-179
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,12 @@ To run the sample follow the below steps:
128128
the new Kinesis Video stream might be delayed significantly.
129129

130130
## Release Notes
131+
### Release 1.0.15 (Aug 2020)
132+
* Added new cluster packing option to the `OputputSegmentMerger` to enable creation of a playable MKV file from a sparse KVS stream.
133+
* Added parsing of audio specific fields from the MKV track header.
134+
* Bump some dependency versions.
135+
* Modify the log level on some log messages.
136+
131137
### Release 1.0.14 (Aug 2019)
132138
* Fixed frame timecode during re-encoding in KinesisVideoRekognitionLambdaExample
133139
* Fixed region for derived KVS Stream

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<artifactId>amazon-kinesis-video-streams-parser-library</artifactId>
1212
<packaging>jar</packaging>
1313
<name>Amazon Kinesis Video Streams Parser Library</name>
14-
<version>1.0.14</version>
14+
<version>1.0.15</version>
1515
<description>The Amazon Kinesis Video Streams Parser Library for Java enables Java developers to parse the streams
1616
returned by GetMedia calls to Amazon Kinesis Video.
1717
</description>

src/main/java/com/amazonaws/kinesisvideo/parser/ebml/EBMLParser.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public EBMLParser(EBMLTypeInfoProvider typeInfoProvider,
8585
this.masterElements = new Stack<>();
8686
this.maxContentBytesInOnePass = maxContentBytesInOnePass;
8787
this.skipBuffer = ByteBuffer.allocate(maxContentBytesInOnePass);
88-
log.info("Creating EBMLParser with maxContentBytesInOnePass {}", this.maxContentBytesInOnePass);
88+
log.debug("Creating EBMLParser with maxContentBytesInOnePass {}", this.maxContentBytesInOnePass);
8989
}
9090

9191
public void parse(ParserByteSource byteSource) {
@@ -155,16 +155,16 @@ public void parse(ParserByteSource byteSource) {
155155

156156
public void closeParser() {
157157
if (!closed) {
158-
log.info("Closing EBMLParser");
158+
log.debug("Closing EBMLParser");
159159
//close current element
160160
if (currentElement != null && currentElement.isKnownType()) {
161-
log.info("Closing with currentElement {} still set, invoking end element callback on it",
161+
log.debug("Closing with currentElement {} still set, invoking end element callback on it",
162162
currentElement);
163163
invokeOnEndElementCallback(currentElement);
164164
currentElement = null;
165165
}
166166

167-
log.info("Closing with {} master elements on stack, invoking end element callback on them",
167+
log.debug("Closing with {} master elements on stack, invoking end element callback on them",
168168
masterElements.size());
169169
while (!masterElements.isEmpty()) {
170170
EBMLParserInternalElement top = masterElements.pop();

src/main/java/com/amazonaws/kinesisvideo/parser/mkv/Frame.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
*/
3333
@Getter
3434
@AllArgsConstructor(access=AccessLevel.PRIVATE)
35-
@Builder
35+
@Builder(toBuilder = true)
3636
@ToString(exclude = {"frameData"})
3737
public class Frame {
3838
private final long trackNumber;

src/main/java/com/amazonaws/kinesisvideo/parser/mkv/MkvStreamReaderCallback.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public void onStartElement(EBMLElementMetaData elementMetaData,
6565
} else {
6666
if (elementDataSize > readBuffer.capacity()) {
6767
int sizeToAllocate = ((int )Math.ceil((double )elementDataSize/MAX_BUFFER_SIZE))*MAX_BUFFER_SIZE;
68-
log.info("Resizing readBuffer to {}", sizeToAllocate);
68+
log.debug("Resizing readBuffer to {}", sizeToAllocate);
6969
readBuffer = ByteBuffer.allocate(sizeToAllocate);
7070
}
7171
readBuffer.clear();

src/main/java/com/amazonaws/kinesisvideo/parser/mkv/StreamingMkvReader.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,14 @@ public boolean mightHaveNext() {
102102
if( !byteSource.eof() && !parser.isClosed()) {
103103
return true;
104104
} else if (byteSource.eof()) {
105-
log.info("byteSource has reached eof");
105+
log.debug("byteSource has reached eof");
106106
if(!parser.isClosed()) {
107-
log.info("byteSource has reached eof and calling close on parser");
107+
log.debug("byteSource has reached eof and calling close on parser");
108108
parser.closeParser();
109109
return true;
110110
}
111111
}
112-
log.info("No more elements to process byteSource.eof {} parser.isClosed {} ",
112+
log.debug("No more elements to process byteSource.eof {} parser.isClosed {} ",
113113
byteSource.eof(),
114114
parser.isClosed());
115115
return false;

src/main/java/com/amazonaws/kinesisvideo/parser/utilities/FragmentMetadataVisitor.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,12 @@ private void createTrackMetadata(List<MkvElement> trackEntryPropertyLists) {
278278
.trackName(getStringVal(metaDataProperties, MkvTypeInfos.NAME))
279279
.codecId(getStringVal(metaDataProperties, MkvTypeInfos.CODECID))
280280
.codecName(getStringVal(metaDataProperties, MkvTypeInfos.CODECNAME))
281+
.codecPrivateData(getByteBuffer(metaDataProperties, MkvTypeInfos.CODECPRIVATE))
281282
.pixelWidth(getUnsignedLongValOptional(metaDataProperties, MkvTypeInfos.PIXELWIDTH))
282283
.pixelHeight(getUnsignedLongValOptional(metaDataProperties, MkvTypeInfos.PIXELHEIGHT))
283-
.codecPrivateData(getByteBuffer(metaDataProperties, MkvTypeInfos.CODECPRIVATE))
284+
.samplingFrequency(getFloatingPointValOptional(metaDataProperties, MkvTypeInfos.SAMPLINGFREQUENCY))
285+
.channels(getUnsignedLongValOptional(metaDataProperties, MkvTypeInfos.CHANNELS))
286+
.bitDepth(getUnsignedLongValOptional(metaDataProperties, MkvTypeInfos.BITDEPTH))
284287
.allElementsInTrack(trackEntryPropertyLists)
285288
.build();
286289

@@ -293,7 +296,6 @@ private static String getStringVal(Map<EBMLTypeInfo, MkvElement> metaDataPropert
293296
return null;
294297
}
295298
MkvDataElement dataElement = (MkvDataElement)element;
296-
Validate.notNull(dataElement);
297299
Validate.isTrue(EBMLTypeInfo.TYPE.STRING.equals(dataElement.getElementMetaData().getTypeInfo().getType())
298300
|| EBMLTypeInfo.TYPE.UTF_8.equals(dataElement.getElementMetaData().getTypeInfo().getType()));
299301
return ((MkvValue<String>)dataElement.getValueCopy()).getVal();
@@ -310,18 +312,31 @@ private static BigInteger getUnsignedLongVal(Map<EBMLTypeInfo, MkvElement> metaD
310312
return null;
311313
}
312314
MkvDataElement dataElement = (MkvDataElement) element;
313-
Validate.notNull(dataElement);
314315
Validate.isTrue(EBMLTypeInfo.TYPE.UINTEGER.equals(dataElement.getElementMetaData().getTypeInfo().getType()));
315316
return ((MkvValue<BigInteger>) dataElement.getValueCopy()).getVal();
316317
}
317318

319+
private static Optional<Double> getFloatingPointValOptional(Map<EBMLTypeInfo, MkvElement> metaDataProperties,
320+
EBMLTypeInfo key) {
321+
return Optional.ofNullable(getFloatingPointVal(metaDataProperties, key));
322+
}
323+
324+
private static Double getFloatingPointVal(Map<EBMLTypeInfo, MkvElement> metaDataProperties, EBMLTypeInfo key) {
325+
MkvElement element = metaDataProperties.get(key);
326+
if (element == null) {
327+
return null;
328+
}
329+
MkvDataElement dataElement = (MkvDataElement) element;
330+
Validate.isTrue(EBMLTypeInfo.TYPE.FLOAT.equals(dataElement.getElementMetaData().getTypeInfo().getType()));
331+
return ((MkvValue<Double>) dataElement.getValueCopy()).getVal();
332+
}
333+
318334
private static ByteBuffer getByteBuffer(Map<EBMLTypeInfo, MkvElement> metaDataProperties, EBMLTypeInfo key) {
319335
MkvElement element = metaDataProperties.get(key);
320336
if (element == null) {
321337
return null;
322338
}
323339
MkvDataElement dataElement = (MkvDataElement)element;
324-
Validate.notNull(dataElement);
325340
Validate.isTrue(EBMLTypeInfo.TYPE.BINARY.equals(dataElement.getElementMetaData().getTypeInfo().getType()));
326341
return ((MkvValue<ByteBuffer>)dataElement.getValueCopy()).getVal();
327342
}

src/main/java/com/amazonaws/kinesisvideo/parser/utilities/FrameVisitor.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
*/
1414
package com.amazonaws.kinesisvideo.parser.utilities;
1515

16-
import java.util.Optional;
17-
1816
import com.amazonaws.kinesisvideo.parser.ebml.MkvTypeInfos;
1917
import com.amazonaws.kinesisvideo.parser.mkv.Frame;
2018
import com.amazonaws.kinesisvideo.parser.mkv.FrameProcessException;
@@ -25,13 +23,18 @@
2523
import org.apache.commons.lang3.NotImplementedException;
2624
import org.apache.commons.lang3.Validate;
2725

26+
import java.math.BigInteger;
27+
import java.util.Optional;
28+
2829
@Slf4j
2930
public class FrameVisitor extends CompositeMkvElementVisitor {
3031
private final FragmentMetadataVisitor fragmentMetadataVisitor;
3132
private final FrameVisitorInternal frameVisitorInternal;
3233
private final FrameProcessor frameProcessor;
3334
private final Optional<Long> trackNumber;
3435
private final Optional<FragmentMetadataVisitor.MkvTagProcessor> tagProcessor;
36+
private Optional<BigInteger> timescale;
37+
private Optional<BigInteger> fragmentTimecode;
3538

3639
private FrameVisitor(final FragmentMetadataVisitor fragmentMetadataVisitor,
3740
final Optional<FragmentMetadataVisitor.MkvTagProcessor> tagProcessor,
@@ -43,6 +46,8 @@ private FrameVisitor(final FragmentMetadataVisitor fragmentMetadataVisitor,
4346
this.frameProcessor = frameProcessor;
4447
this.tagProcessor = tagProcessor;
4548
this.trackNumber = trackNumber;
49+
this.timescale = Optional.empty();
50+
this.fragmentTimecode = Optional.empty();
4651
}
4752

4853
public static FrameVisitor create(final FrameProcessor frameProcessor) {
@@ -83,6 +88,14 @@ default void process(final Frame frame, final MkvTrackMetadata trackMetadata,
8388
}
8489
}
8590

91+
default void process(final Frame frame, final MkvTrackMetadata trackMetadata,
92+
final Optional<FragmentMetadata> fragmentMetadata,
93+
final Optional<FragmentMetadataVisitor.MkvTagProcessor> tagProcessor,
94+
final Optional<BigInteger> timescale, final Optional<BigInteger> fragmentTimecode)
95+
throws FrameProcessException {
96+
process(frame, trackMetadata, fragmentMetadata, tagProcessor);
97+
}
98+
8699
@Override
87100
default void close() {
88101
//No op close. Derived classes should implement this method to meaningfully handle cleanup of the
@@ -108,6 +121,15 @@ public void visit(final com.amazonaws.kinesisvideo.parser.mkv.MkvEndMasterElemen
108121
@Override
109122
public void visit(final com.amazonaws.kinesisvideo.parser.mkv.MkvDataElement dataElement)
110123
throws com.amazonaws.kinesisvideo.parser.mkv.MkvElementVisitException {
124+
125+
if (MkvTypeInfos.TIMECODESCALE.equals(dataElement.getElementMetaData().getTypeInfo())) {
126+
timescale = Optional.of((BigInteger) dataElement.getValueCopy().getVal());
127+
}
128+
129+
if (MkvTypeInfos.TIMECODE.equals(dataElement.getElementMetaData().getTypeInfo())) {
130+
fragmentTimecode = Optional.of((BigInteger) dataElement.getValueCopy().getVal());
131+
}
132+
111133
if (MkvTypeInfos.SIMPLEBLOCK.equals(dataElement.getElementMetaData().getTypeInfo())) {
112134
final MkvValue<Frame> frame = dataElement.getValueCopy();
113135
Validate.notNull(frame);
@@ -118,7 +140,7 @@ public void visit(final com.amazonaws.kinesisvideo.parser.mkv.MkvDataElement dat
118140
if (trackNumber.orElse(frameTrackNo) == frameTrackNo) {
119141
frameProcessor.process(frame.getVal(), trackMetadata,
120142
fragmentMetadataVisitor.getCurrentFragmentMetadata(),
121-
tagProcessor);
143+
tagProcessor, timescale, fragmentTimecode);
122144
}
123145
}
124146
}

src/main/java/com/amazonaws/kinesisvideo/parser/utilities/MkvChildElementCollector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public class MkvChildElementCollector extends MkvElementVisitor {
4040
public MkvChildElementCollector(EBMLTypeInfo parentTypeInfo) {
4141
Validate.isTrue(parentTypeInfo.getType().equals(EBMLTypeInfo.TYPE.MASTER),
4242
"ChildElementCollectors can only collect children for master elements");
43-
log.info("MkvChildElementCollector for element {}", parentTypeInfo);
43+
log.debug("MkvChildElementCollector for element {}", parentTypeInfo);
4444
this.parentTypeInfo = parentTypeInfo;
4545
}
4646

src/main/java/com/amazonaws/kinesisvideo/parser/utilities/MkvTrackMetadata.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import java.nio.ByteBuffer;
2525
import java.util.List;
2626
import java.util.Optional;
27-
import java.util.OptionalLong;
2827

2928
/**
3029
* Class that captures the meta-data for a particular track in the mkv response.
@@ -46,10 +45,19 @@ public class MkvTrackMetadata {
4645
private String codecName = "";
4746
private ByteBuffer codecPrivateData;
4847

48+
// Video track specific
4949
@Builder.Default
5050
private Optional<BigInteger> pixelWidth = Optional.empty();
5151
@Builder.Default
5252
private Optional<BigInteger> pixelHeight = Optional.empty();
5353

54+
// Audio track specific
55+
@Builder.Default
56+
private Optional<Double> samplingFrequency = Optional.empty();
57+
@Builder.Default
58+
private Optional<BigInteger> channels = Optional.empty();
59+
@Builder.Default
60+
private Optional<BigInteger> bitDepth = Optional.empty();
61+
5462
private List<MkvElement> allElementsInTrack;
5563
}

0 commit comments

Comments
 (0)