FFmpeg  4.0
s337m.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2017 foo86
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "libavutil/intreadwrite.h"
22 #include "avformat.h"
23 #include "spdif.h"
24 
25 #define MARKER_16LE 0x72F81F4E
26 #define MARKER_20LE 0x20876FF0E154
27 #define MARKER_24LE 0x72F8961F4EA5
28 
29 #define IS_16LE_MARKER(state) ((state & 0xFFFFFFFF) == MARKER_16LE)
30 #define IS_20LE_MARKER(state) ((state & 0xF0FFFFF0FFFF) == MARKER_20LE)
31 #define IS_24LE_MARKER(state) ((state & 0xFFFFFFFFFFFF) == MARKER_24LE)
32 #define IS_LE_MARKER(state) (IS_16LE_MARKER(state) || IS_20LE_MARKER(state) || IS_24LE_MARKER(state))
33 
35  uint64_t state,
36  int data_type, int data_size,
37  int *offset, enum AVCodecID *codec)
38 {
39  int word_bits;
40 
41  if (IS_16LE_MARKER(state)) {
42  word_bits = 16;
43  } else if (IS_20LE_MARKER(state)) {
44  data_type >>= 8;
45  data_size >>= 4;
46  word_bits = 20;
47  } else {
48  data_type >>= 8;
49  word_bits = 24;
50  }
51 
52  if ((data_type & 0x1F) != 0x1C) {
53  if (s)
54  avpriv_report_missing_feature(s, "Data type %#x in SMPTE 337M", data_type & 0x1F);
55  return AVERROR_PATCHWELCOME;
56  }
57 
58  if (codec)
59  *codec = AV_CODEC_ID_DOLBY_E;
60 
61  switch (data_size / word_bits) {
62  case 3648:
63  *offset = 1920;
64  break;
65  case 3644:
66  *offset = 2002;
67  break;
68  case 3640:
69  *offset = 2000;
70  break;
71  case 3040:
72  *offset = 1601;
73  break;
74  default:
75  if (s)
76  avpriv_report_missing_feature(s, "Dolby E data size %d in SMPTE 337M", data_size);
77  return AVERROR_PATCHWELCOME;
78  }
79 
80  *offset -= 4;
81  *offset *= (word_bits + 7 >> 3) * 2;
82  return 0;
83 }
84 
85 static int s337m_probe(AVProbeData *p)
86 {
87  uint64_t state = 0;
88  int markers[3] = { 0 };
89  int i, pos, sum, max, data_type, data_size, offset;
90  uint8_t *buf;
91 
92  for (pos = 0; pos < p->buf_size; pos++) {
93  state = (state << 8) | p->buf[pos];
94  if (!IS_LE_MARKER(state))
95  continue;
96 
97  buf = p->buf + pos + 1;
98  if (IS_16LE_MARKER(state)) {
99  data_type = AV_RL16(buf );
100  data_size = AV_RL16(buf + 2);
101  } else {
102  data_type = AV_RL24(buf );
103  data_size = AV_RL24(buf + 3);
104  }
105 
106  if (s337m_get_offset_and_codec(NULL, state, data_type, data_size, &offset, NULL))
107  continue;
108 
109  i = IS_16LE_MARKER(state) ? 0 : IS_20LE_MARKER(state) ? 1 : 2;
110  markers[i]++;
111 
112  pos += IS_16LE_MARKER(state) ? 4 : 6;
113  pos += offset;
114  state = 0;
115  }
116 
117  sum = max = 0;
118  for (i = 0; i < FF_ARRAY_ELEMS(markers); i++) {
119  sum += markers[i];
120  if (markers[max] < markers[i])
121  max = i;
122  }
123 
124  if (markers[max] > 3 && markers[max] * 4 > sum * 3)
125  return AVPROBE_SCORE_EXTENSION + 1;
126 
127  return 0;
128 }
129 
131 {
133  return 0;
134 }
135 
136 static void bswap_buf24(uint8_t *data, int size)
137 {
138  int i;
139 
140  for (i = 0; i < size / 3; i++, data += 3)
141  FFSWAP(uint8_t, data[0], data[2]);
142 }
143 
145 {
146  AVIOContext *pb = s->pb;
147  uint64_t state = 0;
148  int ret, data_type, data_size, offset;
149  enum AVCodecID codec;
150  int64_t pos;
151 
152  while (!IS_LE_MARKER(state)) {
153  state = (state << 8) | avio_r8(pb);
154  if (avio_feof(pb))
155  return AVERROR_EOF;
156  }
157 
158  if (IS_16LE_MARKER(state)) {
159  data_type = avio_rl16(pb);
160  data_size = avio_rl16(pb);
161  } else {
162  data_type = avio_rl24(pb);
163  data_size = avio_rl24(pb);
164  }
165 
166  pos = avio_tell(pb);
167 
168  if ((ret = s337m_get_offset_and_codec(s, state, data_type, data_size, &offset, &codec)) < 0)
169  return ret;
170 
171  if ((ret = av_new_packet(pkt, offset)) < 0)
172  return ret;
173 
174  pkt->pos = pos;
175 
176  if (avio_read(pb, pkt->data, pkt->size) < pkt->size) {
177  av_packet_unref(pkt);
178  return AVERROR_EOF;
179  }
180 
181  if (IS_16LE_MARKER(state))
182  ff_spdif_bswap_buf16((uint16_t *)pkt->data, (uint16_t *)pkt->data, pkt->size >> 1);
183  else
184  bswap_buf24(pkt->data, pkt->size);
185 
186  if (!s->nb_streams) {
188  if (!st) {
189  av_packet_unref(pkt);
190  return AVERROR(ENOMEM);
191  }
193  st->codecpar->codec_id = codec;
194  }
195 
196  return 0;
197 }
198 
200  .name = "s337m",
201  .long_name = NULL_IF_CONFIG_SMALL("SMPTE 337M"),
202  .read_probe = s337m_probe,
203  .read_header = s337m_read_header,
204  .read_packet = s337m_read_packet,
205  .flags = AVFMT_GENERIC_INDEX,
206 };
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:768
Bytestream IO Context.
Definition: avio.h:161
int size
int64_t pos
byte position in stream, -1 if unknown
Definition: avcodec.h:1450
static void bswap_buf24(uint8_t *data, int size)
Definition: s337m.c:136
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3884
int size
Definition: avcodec.h:1431
#define AV_RL16
Definition: intreadwrite.h:42
static AVPacket pkt
void ff_spdif_bswap_buf16(uint16_t *dst, const uint16_t *src, int w)
Definition: spdif.c:26
int ctx_flags
Flags signalling stream properties.
Definition: avformat.h:1391
Format I/O context.
Definition: avformat.h:1342
uint8_t
#define AVFMTCTX_NOHEADER
signal that no header is present (streams are added dynamically)
Definition: avformat.h:1286
#define IS_16LE_MARKER(state)
Definition: s337m.c:29
#define IS_LE_MARKER(state)
Definition: s337m.c:32
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4441
const char data[16]
Definition: mxf.c:90
uint8_t * data
Definition: avcodec.h:1430
#define AVERROR_EOF
End of file.
Definition: error.h:55
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:648
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:86
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: avcodec.h:215
static int s337m_read_header(AVFormatContext *s)
Definition: s337m.c:130
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
static int s337m_get_offset_and_codec(AVFormatContext *s, uint64_t state, int data_type, int data_size, int *offset, enum AVCodecID *codec)
Definition: s337m.c:34
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3880
static const uint8_t offset[127][2]
Definition: vf_spp.c:92
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:639
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:451
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:450
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1398
static struct @271 state
if(ret< 0)
Definition: vf_mcdeint.c:279
#define FF_ARRAY_ELEMS(a)
Stream structure.
Definition: avformat.h:873
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
AVIOContext * pb
I/O context.
Definition: avformat.h:1384
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:592
void * buf
Definition: avisynth_c.h:690
#define AVFMT_GENERIC_INDEX
Use generic index building code.
Definition: avformat.h:470
#define AVPROBE_SCORE_EXTENSION
score for file extension
Definition: avformat.h:458
AVInputFormat ff_s337m_demuxer
Definition: s337m.c:199
This structure contains the data a format has to probe a file.
Definition: avformat.h:448
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
#define AV_RL24
Definition: intreadwrite.h:78
static int s337m_probe(AVProbeData *p)
Definition: s337m.c:85
static int s337m_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: s337m.c:144
unsigned int avio_rl16(AVIOContext *s)
Definition: aviobuf.c:754
Main libavformat public API header.
#define IS_20LE_MARKER(state)
Definition: s337m.c:30
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:647
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1020
int avio_feof(AVIOContext *s)
feof() equivalent for AVIOContext.
Definition: aviobuf.c:358
#define FFSWAP(type, a, b)
Definition: common.h:99
unsigned int avio_rl24(AVIOContext *s)
Definition: aviobuf.c:762
This structure stores compressed data.
Definition: avcodec.h:1407