Skip to content

Commit 7abf124

Browse files
committed
Enrich mov mp4 webm probe metadata
extract additional stream metadata for mov/mp4/webm probes, including codec details, frame rate, bit depth, per-track bitrate, and display aspect ratio when available. map new probe values into stream and tag output in the stub engine so callers receive richer video/audio metadata consistently. add bitrate/aspect-ratio fallbacks from container size and duration, and guard conversion route resolution against null media types. bump project version to 1.0.4 and document the new probe fields in the changelog and readme.
1 parent 5c8d824 commit 7abf124

File tree

11 files changed

+609
-26
lines changed

11 files changed

+609
-26
lines changed

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.0.4] - 2026-03-05
9+
10+
### Added
11+
- Added richer MOV probe fields in [`MovProbeInfo`](src/main/java/me/tamkungz/codecmedia/internal/video/mov/MovProbeInfo.java): `videoBitrateKbps`, `audioBitrateKbps`, `bitDepth`, and `displayAspectRatio`.
12+
- Added richer MP4 probe fields in [`Mp4ProbeInfo`](src/main/java/me/tamkungz/codecmedia/internal/video/mp4/Mp4ProbeInfo.java): codec/audio stream details, frame rate, bitrate fields, bit depth, and display aspect ratio.
13+
- Added richer WebM probe fields in [`WebmProbeInfo`](src/main/java/me/tamkungz/codecmedia/internal/video/webm/WebmProbeInfo.java): per-track bitrate fields and display aspect ratio.
14+
15+
### Changed
16+
- Enhanced MOV parsing in [`MovParser`](src/main/java/me/tamkungz/codecmedia/internal/video/mov/MovParser.java) with deeper BMFF track metadata extraction (`hdlr`, `mdhd`, `stsd`, `btrt`, `stsz`) and fallback bitrate estimation.
17+
- Enhanced MP4 parsing in [`Mp4Parser`](src/main/java/me/tamkungz/codecmedia/internal/video/mp4/Mp4Parser.java) to extract video/audio codec, sample rate, channels, frame rate, bit depth, bitrate, and aspect ratio.
18+
- Enhanced WebM parsing in [`WebmParser`](src/main/java/me/tamkungz/codecmedia/internal/video/webm/WebmParser.java) to extract track bitrate when present and compute fallback bitrate/aspect ratio values.
19+
- Updated stream/tag mapping in [`StubCodecMediaEngine`](src/main/java/me/tamkungz/codecmedia/internal/StubCodecMediaEngine.java) so MOV/MP4/WebM probe results now expose richer stream bitrate and container tags (`displayAspectRatio`, `bitDepth`, `videoBitrateKbps`, `audioBitrateKbps`).
20+
21+
### Verified
22+
- Confirmed test stability after video parser improvements with `mvn test`.
23+
824
## [1.0.3] - 2026-03-05
925

1026
### Added

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ CodecMedia is a Java library for media probing, validation, metadata sidecar per
2828
- MP4 (basic ISO BMFF parsing)
2929
- WebM (EBML container parsing)
3030
- Validation with size limits and strict parser checks for MP3/OGG/WAV/PNG/JPEG/WebP/BMP/TIFF/HEIC/HEIF/AVIF/MOV/MP4/WebM
31+
- MOV/MP4/WebM probe tags now include richer video metadata when present (for example `displayAspectRatio`, `bitDepth`, `videoBitrateKbps`, `audioBitrateKbps`)
3132
- Metadata read/write with sidecar persistence (`.codecmedia.properties`)
3233
- In-Java extraction and conversion file operations
3334
- Image-to-image conversion in Java for: `png`, `jpg`/`jpeg`, `webp`, `bmp`, `tif`/`tiff`, `heic`/`heif`
@@ -101,3 +102,4 @@ This project is licensed under the Apache License 2.0.
101102
---
102103

103104
*by TamKungZ_*
105+

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
<groupId>me.tamkungz.codecmedia</groupId>
99
<artifactId>codecmedia</artifactId>
10-
<version>1.0.3</version>
10+
<version>1.0.4</version>
1111
<packaging>jar</packaging>
1212

1313
<name>CodecMedia</name>

src/main/java/me/tamkungz/codecmedia/internal/StubCodecMediaEngine.java

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -376,17 +376,29 @@ public ProbeResult probe(Path input) throws CodecMediaException {
376376
if (info.audioCodec() != null && !info.audioCodec().isBlank()) {
377377
tags.put("audioCodec", info.audioCodec());
378378
}
379+
if (info.displayAspectRatio() != null && !info.displayAspectRatio().isBlank()) {
380+
tags.put("displayAspectRatio", info.displayAspectRatio());
381+
}
382+
if (info.bitDepth() != null && info.bitDepth() > 0) {
383+
tags.put("bitDepth", String.valueOf(info.bitDepth()));
384+
}
385+
if (info.videoBitrateKbps() != null && info.videoBitrateKbps() > 0) {
386+
tags.put("videoBitrateKbps", String.valueOf(info.videoBitrateKbps()));
387+
}
388+
if (info.audioBitrateKbps() != null && info.audioBitrateKbps() > 0) {
389+
tags.put("audioBitrateKbps", String.valueOf(info.audioBitrateKbps()));
390+
}
379391

380392
java.util.ArrayList<StreamInfo> streams = new java.util.ArrayList<>();
381393
if (info.width() != null && info.height() != null && info.width() > 0 && info.height() > 0) {
382-
streams.add(new StreamInfo(0, StreamKind.VIDEO, info.videoCodec() != null ? info.videoCodec() : "unknown", null, null, null, info.width(), info.height(), info.frameRate()));
394+
streams.add(new StreamInfo(0, StreamKind.VIDEO, info.videoCodec() != null ? info.videoCodec() : "unknown", info.videoBitrateKbps(), null, null, info.width(), info.height(), info.frameRate()));
383395
}
384396
if (info.sampleRate() != null && info.channels() != null && info.sampleRate() > 0 && info.channels() > 0) {
385397
streams.add(new StreamInfo(
386398
streams.size(),
387399
StreamKind.AUDIO,
388400
info.audioCodec() != null ? info.audioCodec() : "unknown",
389-
null,
401+
info.audioBitrateKbps(),
390402
info.sampleRate(),
391403
info.channels(),
392404
null,
@@ -421,12 +433,51 @@ public ProbeResult probe(Path input) throws CodecMediaException {
421433
if (info.majorBrand() != null && !info.majorBrand().isBlank()) {
422434
tags.put("majorBrand", info.majorBrand());
423435
}
436+
if (info.videoCodec() != null && !info.videoCodec().isBlank()) {
437+
tags.put("videoCodec", info.videoCodec());
438+
}
439+
if (info.audioCodec() != null && !info.audioCodec().isBlank()) {
440+
tags.put("audioCodec", info.audioCodec());
441+
}
442+
if (info.displayAspectRatio() != null && !info.displayAspectRatio().isBlank()) {
443+
tags.put("displayAspectRatio", info.displayAspectRatio());
444+
}
445+
if (info.bitDepth() != null && info.bitDepth() > 0) {
446+
tags.put("bitDepth", String.valueOf(info.bitDepth()));
447+
}
448+
if (info.videoBitrateKbps() != null && info.videoBitrateKbps() > 0) {
449+
tags.put("videoBitrateKbps", String.valueOf(info.videoBitrateKbps()));
450+
}
451+
if (info.audioBitrateKbps() != null && info.audioBitrateKbps() > 0) {
452+
tags.put("audioBitrateKbps", String.valueOf(info.audioBitrateKbps()));
453+
}
424454

425-
List<StreamInfo> streams;
455+
java.util.ArrayList<StreamInfo> streams = new java.util.ArrayList<>();
426456
if (mediaType == MediaType.VIDEO && info.width() != null && info.height() != null && info.width() > 0 && info.height() > 0) {
427-
streams = List.of(new StreamInfo(0, StreamKind.VIDEO, "h264/unknown", null, null, null, info.width(), info.height(), null));
428-
} else {
429-
streams = List.of();
457+
streams.add(new StreamInfo(
458+
streams.size(),
459+
StreamKind.VIDEO,
460+
info.videoCodec() != null ? info.videoCodec() : "unknown",
461+
info.videoBitrateKbps(),
462+
null,
463+
null,
464+
info.width(),
465+
info.height(),
466+
info.frameRate()
467+
));
468+
}
469+
if (info.sampleRate() != null && info.channels() != null && info.sampleRate() > 0 && info.channels() > 0) {
470+
streams.add(new StreamInfo(
471+
streams.size(),
472+
StreamKind.AUDIO,
473+
info.audioCodec() != null ? info.audioCodec() : "unknown",
474+
info.audioBitrateKbps(),
475+
info.sampleRate(),
476+
info.channels(),
477+
null,
478+
null,
479+
null
480+
));
430481
}
431482

432483
return new ProbeResult(
@@ -435,7 +486,7 @@ public ProbeResult probe(Path input) throws CodecMediaException {
435486
outputExt,
436487
mediaType,
437488
info.durationMillis(),
438-
streams,
489+
List.copyOf(streams),
439490
tags
440491
);
441492
} catch (CodecMediaException ignored) {
@@ -455,17 +506,29 @@ public ProbeResult probe(Path input) throws CodecMediaException {
455506
if (info.audioCodec() != null && !info.audioCodec().isBlank()) {
456507
tags.put("audioCodec", info.audioCodec());
457508
}
509+
if (info.displayAspectRatio() != null && !info.displayAspectRatio().isBlank()) {
510+
tags.put("displayAspectRatio", info.displayAspectRatio());
511+
}
512+
if (info.bitDepth() != null && info.bitDepth() > 0) {
513+
tags.put("bitDepth", String.valueOf(info.bitDepth()));
514+
}
515+
if (info.videoBitrateKbps() != null && info.videoBitrateKbps() > 0) {
516+
tags.put("videoBitrateKbps", String.valueOf(info.videoBitrateKbps()));
517+
}
518+
if (info.audioBitrateKbps() != null && info.audioBitrateKbps() > 0) {
519+
tags.put("audioBitrateKbps", String.valueOf(info.audioBitrateKbps()));
520+
}
458521

459522
java.util.ArrayList<StreamInfo> streams = new java.util.ArrayList<>();
460523
if (info.width() != null && info.height() != null && info.width() > 0 && info.height() > 0) {
461-
streams.add(new StreamInfo(0, StreamKind.VIDEO, info.videoCodec() != null ? info.videoCodec() : "unknown", null, null, null, info.width(), info.height(), info.frameRate()));
524+
streams.add(new StreamInfo(0, StreamKind.VIDEO, info.videoCodec() != null ? info.videoCodec() : "unknown", info.videoBitrateKbps(), null, null, info.width(), info.height(), info.frameRate()));
462525
}
463526
if (info.sampleRate() != null && info.channels() != null && info.sampleRate() > 0 && info.channels() > 0) {
464527
streams.add(new StreamInfo(
465528
streams.size(),
466529
StreamKind.AUDIO,
467530
info.audioCodec() != null ? info.audioCodec() : "unknown",
468-
null,
531+
info.audioBitrateKbps(),
469532
info.sampleRate(),
470533
info.channels(),
471534
null,

src/main/java/me/tamkungz/codecmedia/internal/convert/ConversionRouteResolver.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ private ConversionRouteResolver() {
88
}
99

1010
public static ConversionRoute resolve(MediaType source, MediaType target) {
11+
if (source == null || target == null) {
12+
return ConversionRoute.UNSUPPORTED;
13+
}
1114
if (source == MediaType.AUDIO && target == MediaType.AUDIO) {
1215
return ConversionRoute.AUDIO_TO_AUDIO;
1316
}

0 commit comments

Comments
 (0)