FFmpeg  4.4.4
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 
34 static int s337m_get_offset_and_codec(void *avc,
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 (avc)
54  avpriv_report_missing_feature(avc, "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 (avc)
76  avpriv_report_missing_feature(avc, "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(const 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];
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 {
132  s->ctx_flags |= AVFMTCTX_NOHEADER;
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  return AVERROR_EOF;
178  }
179 
180  if (IS_16LE_MARKER(state))
181  ff_spdif_bswap_buf16((uint16_t *)pkt->data, (uint16_t *)pkt->data, pkt->size >> 1);
182  else
184 
185  if (!s->nb_streams) {
187  if (!st) {
188  return AVERROR(ENOMEM);
189  }
191  st->codecpar->codec_id = codec;
192  }
193 
194  return 0;
195 }
196 
198  .name = "s337m",
199  .long_name = NULL_IF_CONFIG_SMALL("SMPTE 337M"),
200  .read_probe = s337m_probe,
201  .read_header = s337m_read_header,
202  .read_packet = s337m_read_packet,
203  .flags = AVFMT_GENERIC_INDEX,
204 };
uint8_t
Main libavformat public API header.
#define AVFMTCTX_NOHEADER
signal that no header is present (streams are added dynamically)
Definition: avformat.h:1177
#define AVPROBE_SCORE_EXTENSION
score for file extension
Definition: avformat.h:451
#define AVFMT_GENERIC_INDEX
Use generic index building code.
Definition: avformat.h:463
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:364
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
unsigned int avio_rl16(AVIOContext *s)
Definition: aviobuf.c:734
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:633
unsigned int avio_rl24(AVIOContext *s)
Definition: aviobuf.c:742
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:624
#define AV_RL16
Definition: intreadwrite.h:42
#define AV_RL24
Definition: intreadwrite.h:78
#define s(width, name)
Definition: cbs_vp9.c:257
static struct @321 state
#define FFSWAP(type, a, b)
Definition: common.h:108
#define NULL
Definition: coverity.c:32
#define max(a, b)
Definition: cuda_runtime.h:33
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:46
@ AV_CODEC_ID_DOLBY_E
Definition: codec_id.h:509
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:99
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4509
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
#define AVERROR_EOF
End of file.
Definition: error.h:55
#define AVERROR(e)
Definition: error.h:43
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
int i
Definition: input.c:407
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
const char data[16]
Definition: mxf.c:142
static int s337m_read_header(AVFormatContext *s)
Definition: s337m.c:130
static int s337m_probe(const AVProbeData *p)
Definition: s337m.c:85
#define IS_20LE_MARKER(state)
Definition: s337m.c:30
#define IS_LE_MARKER(state)
Definition: s337m.c:32
AVInputFormat ff_s337m_demuxer
Definition: s337m.c:197
#define IS_16LE_MARKER(state)
Definition: s337m.c:29
static int s337m_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: s337m.c:144
static void bswap_buf24(uint8_t *data, int size)
Definition: s337m.c:136
static int s337m_get_offset_and_codec(void *avc, uint64_t state, int data_type, int data_size, int *offset, enum AVCodecID *codec)
Definition: s337m.c:34
#define FF_ARRAY_ELEMS(a)
void ff_spdif_bswap_buf16(uint16_t *dst, const uint16_t *src, int w)
Definition: spdif.c:26
unsigned int pos
Definition: spdifenc.c:412
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
Format I/O context.
Definition: avformat.h:1232
Bytestream IO Context.
Definition: avio.h:161
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:645
This structure stores compressed data.
Definition: packet.h:346
int size
Definition: packet.h:370
uint8_t * data
Definition: packet.h:369
int64_t pos
byte position in stream, -1 if unknown
Definition: packet.h:389
This structure contains the data a format has to probe a file.
Definition: avformat.h:441
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:444
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:443
Stream structure.
Definition: avformat.h:873
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1038
AVPacket * pkt
Definition: movenc.c:59
int size
if(ret< 0)
Definition: vf_mcdeint.c:282
static const uint8_t offset[127][2]
Definition: vf_spp.c:107