This newer format is used by Harris NEXIO playout servers.
---
Changelog | 1 +
libavformat/lxfdec.c | 55 ++++++++++++++++++++++++++++++++++---------------
2 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/Changelog b/Changelog
index 58568c2..e615be4 100644
--- a/Changelog
+++ b/Changelog
@@ -110,6 +110,7 @@ easier to use. The changes are:
- v410 QuickTime uncompressed 4:4:4 10-bit encoder and decoder
- OpenMG Audio muxer
- Simple segmenting muxer
+- Support for version 1 files in the Harris LXF demuxer
version 0.7:
diff --git a/libavformat/lxfdec.c b/libavformat/lxfdec.c
index b3afa7e..2b9a3cf 100644
--- a/libavformat/lxfdec.c
+++ b/libavformat/lxfdec.c
@@ -24,7 +24,7 @@
#include "internal.h"
#include "riff.h"
-#define LXF_PACKET_HEADER_SIZE 60
+#define LXF_PACKET_HEADER_MAX_SIZE 72
#define LXF_HEADER_DATA_SIZE 120
#define LXF_IDENT "LEITCH\0"
#define LXF_IDENT_LENGTH 8
@@ -46,6 +46,7 @@ static const AVCodecTag lxf_tags[] = {
};
typedef struct {
+ int version; ///< LXF file version
int channels; ///< number of audio channels. zero
means no audio
uint8_t temp[LXF_MAX_AUDIO_PACKET]; ///< temp buffer for de-planarizing
the audio data
int frame_number; ///< current video frame
@@ -63,14 +64,15 @@ static int lxf_probe(AVProbeData *p)
* Verify the checksum of an LXF packet header
*
* @param[in] header the packet header to check
+ * @param[in] header_size the size of the packet header
* @return zero if the checksum is OK, non-zero otherwise
*/
-static int check_checksum(const uint8_t *header)
+static int check_checksum(const uint8_t *header, int header_size)
{
int x;
uint32_t sum = 0;
- for (x = 0; x < LXF_PACKET_HEADER_SIZE; x += 4)
+ for (x = 0; x < header_size; x += 4)
sum += AV_RL32(&header[x]);
return sum;
@@ -113,33 +115,43 @@ static int sync(AVFormatContext *s, uint8_t *header)
static int get_packet_header(AVFormatContext *s, uint8_t *header, uint32_t
*format)
{
AVIOContext *pb = s->pb;
- int track_size, samples, ret;
+ LXFDemuxContext *lxf = s->priv_data;
+ int track_size, samples, ret, version, offset, header_size, channels;
AVStream *st;
//find and read the ident
if ((ret = sync(s, header)) < 0)
return ret;
+ //read the version and packet header size
+ if ((ret = avio_read(pb, header + LXF_IDENT_LENGTH, 8)) != 8)
+ return ret < 0 ? ret : AVERROR_EOF;
+ lxf->version = version = AV_RL32(&header[LXF_IDENT_LENGTH]);
+ if (version < 0 || version > 1)
+ av_log(s, AV_LOG_ERROR, "unsupported LXF version: %i\n", version);
+ offset = version == 1 ? 8 : 0;
+ header_size = AV_RL32(&header[LXF_IDENT_LENGTH+4]);
+
//read the rest of the packet header
- if ((ret = avio_read(pb, header + LXF_IDENT_LENGTH,
- LXF_PACKET_HEADER_SIZE - LXF_IDENT_LENGTH)) !=
- LXF_PACKET_HEADER_SIZE - LXF_IDENT_LENGTH) {
+ if ((ret = avio_read(pb, header + LXF_IDENT_LENGTH + 8,
+ header_size - LXF_IDENT_LENGTH - 8)) !=
+ header_size - LXF_IDENT_LENGTH - 8) {
return ret < 0 ? ret : AVERROR_EOF;
}
- if (check_checksum(header))
+ if (check_checksum(header, header_size))
av_log(s, AV_LOG_ERROR, "checksum error\n");
- *format = AV_RL32(&header[32]);
- ret = AV_RL32(&header[36]);
+ *format = AV_RL32(&header[32 + offset]);
+ ret = AV_RL32(&header[36 + offset]);
//type
switch (AV_RL32(&header[16])) {
case 0:
//video
//skip VBI data and metadata
- avio_skip(pb, (int64_t)(uint32_t)AV_RL32(&header[44]) +
- (int64_t)(uint32_t)AV_RL32(&header[52]));
+ avio_skip(pb, (int64_t)(uint32_t)AV_RL32(&header[44 + offset]) +
+ (int64_t)(uint32_t)AV_RL32(&header[52 + offset]));
break;
case 1:
//audio
@@ -185,8 +197,14 @@ static int get_packet_header(AVFormatContext *s, uint8_t
*header, uint32_t *form
avpriv_set_pts_info(s->streams[0], 64, 1, 25);
}
- //TODO: warning if track mask != (1 << channels) - 1?
- ret = av_popcount(AV_RL32(&header[44])) * track_size;
+ channels = av_popcount(AV_RL32(&header[44]));
+ if (channels != lxf->channels) {
+ av_log(s, AV_LOG_DEBUG,
+ "Disk segment indicates %d channels, but audio packet
contains %d.\n",
+ lxf->channels, channels);
+ st->codec->channels = channels = lxf->channels;
+ }
+ ret = channels * track_size;
break;
default:
@@ -200,7 +218,7 @@ static int lxf_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
LXFDemuxContext *lxf = s->priv_data;
AVIOContext *pb = s->pb;
- uint8_t header[LXF_PACKET_HEADER_SIZE], header_data[LXF_HEADER_DATA_SIZE];
+ uint8_t header[LXF_PACKET_HEADER_MAX_SIZE],
header_data[LXF_HEADER_DATA_SIZE];
int ret;
AVStream *st;
uint32_t format, video_params, disk_params;
@@ -256,7 +274,10 @@ static int lxf_read_header(AVFormatContext *s,
AVFormatParameters *ap)
if (format == 1) {
//skip extended field data
- avio_skip(s->pb, (uint32_t)AV_RL32(&header[40]));
+ if (lxf->version)
+ avio_skip(s->pb, (uint32_t)AV_RL32(&header[48]));
+ else
+ avio_skip(s->pb, (uint32_t)AV_RL32(&header[40]));
}
return 0;
@@ -283,7 +304,7 @@ static int lxf_read_packet(AVFormatContext *s, AVPacket
*pkt)
{
LXFDemuxContext *lxf = s->priv_data;
AVIOContext *pb = s->pb;
- uint8_t header[LXF_PACKET_HEADER_SIZE], *buf;
+ uint8_t header[LXF_PACKET_HEADER_MAX_SIZE], *buf;
AVStream *ast = NULL;
uint32_t stream, format;
int ret, ret2;
--
1.7.7.msysgit.1
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel