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

Reply via email to