annotate spdif.c @ 6193:da9998b48dff libavformat

rtpdec: Malloc the fmtp value buffer This allows very large value strings, needed for xiph extradata. Patch by Josh Allmann, joshua dot allmann at gmail
author mstorsjo
date Mon, 28 Jun 2010 20:27:25 +0000
parents 902c290b60ed
children e630da0f5861
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5138
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
1 /*
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
2 * IEC958 muxer
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
3 * Copyright (c) 2009 Bartlomiej Wolowiec
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
4 *
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
5 * This file is part of FFmpeg.
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
6 *
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
11 *
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
15 * Lesser General Public License for more details.
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
16 *
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
20 */
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
21
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
22 /**
5969
178de7695c6c Remove explicit filename from Doxygen @file commands.
diego
parents: 5940
diff changeset
23 * @file
5138
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
24 * IEC-61937 encapsulation of various formats, used by S/PDIF
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
25 * @author Bartlomiej Wolowiec
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
26 */
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
27
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
28 /*
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
29 * Terminology used in specification:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
30 * data-burst - IEC958 frame, contains header and encapsuled frame
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
31 * burst-preambule - IEC958 frame header, contains 16-bits words named Pa, Pb, Pc and Pd
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
32 * burst-payload - encapsuled frame
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
33 * Pa, Pb - syncword - 0xF872, 0x4E1F
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
34 * Pc - burst-info, contains data-type (bits 0-6), error flag (bit 7), data-type-dependent info (bits 8-12)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
35 * and bitstream number (bits 13-15)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
36 * data-type - determines type of encapsuled frames
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
37 * Pd - length code (number of bits or bytes of encapsuled frame - according to data_type)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
38 *
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
39 * IEC958 frames at normal usage start every specific count of bytes,
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
40 * dependent from data-type (spaces between packets are filled by zeros)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
41 */
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
42
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
43 #include "avformat.h"
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
44 #include "libavcodec/ac3.h"
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
45 #include "libavcodec/dca.h"
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
46 #include "libavcodec/aac_parser.h"
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
47
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
48 #define SYNCWORD1 0xF872
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
49 #define SYNCWORD2 0x4E1F
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
50 #define BURST_HEADER_SIZE 0x8
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
51
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
52 enum IEC958DataType {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
53 IEC958_AC3 = 0x01, ///< AC-3 data
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
54 IEC958_MPEG1_LAYER1 = 0x04, ///< MPEG-1 layer 1
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
55 IEC958_MPEG1_LAYER23 = 0x05, ///< MPEG-1 layer 2 or 3 data or MPEG-2 without extension
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
56 IEC958_MPEG2_EXT = 0x06, ///< MPEG-2 data with extension
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
57 IEC958_MPEG2_AAC = 0x07, ///< MPEG-2 AAC ADTS
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
58 IEC958_MPEG2_LAYER1_LSF = 0x08, ///< MPEG-2, layer-1 low sampling frequency
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
59 IEC958_MPEG2_LAYER2_LSF = 0x09, ///< MPEG-2, layer-2 low sampling frequency
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
60 IEC958_MPEG2_LAYER3_LSF = 0x0A, ///< MPEG-2, layer-3 low sampling frequency
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
61 IEC958_DTS1 = 0x0B, ///< DTS type I (512 samples)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
62 IEC958_DTS2 = 0x0C, ///< DTS type II (1024 samples)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
63 IEC958_DTS3 = 0x0D, ///< DTS type III (2048 samples)
6141
e4e0d0ab6ced Add IEC958 data_types for Atrac* and WMA Pro.
cehoyos
parents: 5969
diff changeset
64 IEC958_ATRAC = 0x0E, ///< Atrac data
e4e0d0ab6ced Add IEC958 data_types for Atrac* and WMA Pro.
cehoyos
parents: 5969
diff changeset
65 IEC958_ATRAC3 = 0x0F, ///< Atrac 3 data
e4e0d0ab6ced Add IEC958 data_types for Atrac* and WMA Pro.
cehoyos
parents: 5969
diff changeset
66 IEC958_ATRACX = 0x10, ///< Atrac 3 plus data
6149
902c290b60ed Add IEC958 data_types for DTS-HD (data burst described in IEC 61937-5),
cehoyos
parents: 6141
diff changeset
67 IEC958_DTSHD = 0x11, ///< DTS HD data
6141
e4e0d0ab6ced Add IEC958 data_types for Atrac* and WMA Pro.
cehoyos
parents: 5969
diff changeset
68 IEC958_WMAPRO = 0x12, ///< WMA 9 Professional data
5138
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
69 IEC958_MPEG2_AAC_LSF_2048 = 0x13, ///< MPEG-2 AAC ADTS half-rate low sampling frequency
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
70 IEC958_MPEG2_AAC_LSF_4096 = 0x13 | 0x20, ///< MPEG-2 AAC ADTS quarter-rate low sampling frequency
6149
902c290b60ed Add IEC958 data_types for DTS-HD (data burst described in IEC 61937-5),
cehoyos
parents: 6141
diff changeset
71 IEC958_EAC3 = 0x15, ///< E-AC-3 data
902c290b60ed Add IEC958 data_types for DTS-HD (data burst described in IEC 61937-5),
cehoyos
parents: 6141
diff changeset
72 IEC958_TRUEHD = 0x16, ///< TrueHD data
5138
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
73 };
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
74
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
75 typedef struct IEC958Context {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
76 enum IEC958DataType data_type; ///< burst info - reference to type of payload of the data-burst
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
77 int pkt_size; ///< length code in bits
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
78 int pkt_offset; ///< data burst repetition period in bytes
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
79 uint8_t *buffer; ///< allocated buffer, used for swap bytes
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
80 int buffer_size; ///< size of allocated buffer
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
81
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
82 /// function, which generates codec dependent header information.
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
83 /// Sets data_type and data_offset
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
84 int (*header_info) (AVFormatContext *s, AVPacket *pkt);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
85 } IEC958Context;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
86
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
87 //TODO move to DSP
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
88 static void bswap_buf16(uint16_t *dst, const uint16_t *src, int w)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
89 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
90 int i;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
91
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
92 for (i = 0; i + 8 <= w; i += 8) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
93 dst[i + 0] = bswap_16(src[i + 0]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
94 dst[i + 1] = bswap_16(src[i + 1]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
95 dst[i + 2] = bswap_16(src[i + 2]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
96 dst[i + 3] = bswap_16(src[i + 3]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
97 dst[i + 4] = bswap_16(src[i + 4]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
98 dst[i + 5] = bswap_16(src[i + 5]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
99 dst[i + 6] = bswap_16(src[i + 6]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
100 dst[i + 7] = bswap_16(src[i + 7]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
101 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
102 for (; i < w; i++)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
103 dst[i + 0] = bswap_16(src[i + 0]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
104 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
105
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
106 static int spdif_header_ac3(AVFormatContext *s, AVPacket *pkt)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
107 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
108 IEC958Context *ctx = s->priv_data;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
109 int bitstream_mode = pkt->data[6] & 0x7;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
110
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
111 ctx->data_type = IEC958_AC3 | (bitstream_mode << 8);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
112 ctx->pkt_offset = AC3_FRAME_SIZE << 2;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
113 return 0;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
114 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
115
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
116 static int spdif_header_dts(AVFormatContext *s, AVPacket *pkt)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
117 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
118 IEC958Context *ctx = s->priv_data;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
119 uint32_t syncword_dts = AV_RB32(pkt->data);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
120 int blocks;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
121
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
122 switch (syncword_dts) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
123 case DCA_MARKER_RAW_BE:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
124 blocks = (AV_RB16(pkt->data + 4) >> 2) & 0x7f;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
125 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
126 case DCA_MARKER_RAW_LE:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
127 blocks = (AV_RL16(pkt->data + 4) >> 2) & 0x7f;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
128 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
129 case DCA_MARKER_14B_BE:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
130 blocks =
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
131 (((pkt->data[5] & 0x07) << 4) | ((pkt->data[6] & 0x3f) >> 2));
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
132 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
133 case DCA_MARKER_14B_LE:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
134 blocks =
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
135 (((pkt->data[4] & 0x07) << 4) | ((pkt->data[7] & 0x3f) >> 2));
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
136 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
137 default:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
138 av_log(s, AV_LOG_ERROR, "bad DTS syncword 0x%x\n", syncword_dts);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
139 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
140 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
141 blocks++;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
142 switch (blocks) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
143 case 512 >> 5: ctx->data_type = IEC958_DTS1; break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
144 case 1024 >> 5: ctx->data_type = IEC958_DTS2; break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
145 case 2048 >> 5: ctx->data_type = IEC958_DTS3; break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
146 default:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
147 av_log(s, AV_LOG_ERROR, "%i samples in DTS frame not supported\n",
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
148 blocks << 5);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
149 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
150 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
151 ctx->pkt_offset = blocks << 7;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
152
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
153 return 0;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
154 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
155
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
156 static const enum IEC958DataType mpeg_data_type[2][3] = {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
157 // LAYER1 LAYER2 LAYER3
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
158 { IEC958_MPEG2_LAYER1_LSF, IEC958_MPEG2_LAYER2_LSF, IEC958_MPEG2_LAYER3_LSF }, //MPEG2 LSF
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
159 { IEC958_MPEG1_LAYER1, IEC958_MPEG1_LAYER23, IEC958_MPEG1_LAYER23 }, //MPEG1
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
160 };
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
161
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
162 static const uint16_t mpeg_pkt_offset[2][3] = {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
163 //LAYER1 LAYER2 LAYER3
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
164 { 3072, 9216, 4608 }, // MPEG2 LSF
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
165 { 1536, 4608, 4608 }, // MPEG1
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
166 };
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
167
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
168 static int spdif_header_mpeg(AVFormatContext *s, AVPacket *pkt)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
169 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
170 IEC958Context *ctx = s->priv_data;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
171 int version = (pkt->data[1] >> 3) & 3;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
172 int layer = 3 - ((pkt->data[1] >> 1) & 3);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
173 int extension = pkt->data[2] & 1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
174
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
175 if (layer == 3 || version == 1) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
176 av_log(s, AV_LOG_ERROR, "Wrong MPEG file format\n");
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
177 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
178 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
179 av_log(s, AV_LOG_DEBUG, "version: %i layer: %i extension: %i\n", version, layer, extension);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
180 if (version == 2 && extension) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
181 ctx->data_type = IEC958_MPEG2_EXT;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
182 ctx->pkt_offset = 4608;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
183 } else {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
184 ctx->data_type = mpeg_data_type [version & 1][layer];
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
185 ctx->pkt_offset = mpeg_pkt_offset[version & 1][layer];
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
186 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
187 // TODO Data type dependant info (normal/karaoke, dynamic range control)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
188 return 0;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
189 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
190
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
191 static int spdif_header_aac(AVFormatContext *s, AVPacket *pkt)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
192 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
193 IEC958Context *ctx = s->priv_data;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
194 AACADTSHeaderInfo hdr;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
195 GetBitContext gbc;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
196 int ret;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
197
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
198 init_get_bits(&gbc, pkt->data, AAC_ADTS_HEADER_SIZE * 8);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
199 ret = ff_aac_parse_header(&gbc, &hdr);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
200 if (ret < 0) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
201 av_log(s, AV_LOG_ERROR, "Wrong AAC file format\n");
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
202 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
203 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
204
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
205 ctx->pkt_offset = hdr.samples << 2;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
206 switch (hdr.num_aac_frames) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
207 case 1:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
208 ctx->data_type = IEC958_MPEG2_AAC;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
209 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
210 case 2:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
211 ctx->data_type = IEC958_MPEG2_AAC_LSF_2048;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
212 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
213 case 4:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
214 ctx->data_type = IEC958_MPEG2_AAC_LSF_4096;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
215 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
216 default:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
217 av_log(s, AV_LOG_ERROR, "%i samples in AAC frame not supported\n",
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
218 hdr.samples);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
219 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
220 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
221 //TODO Data type dependent info (LC profile/SBR)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
222 return 0;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
223 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
224
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
225 static int spdif_write_header(AVFormatContext *s)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
226 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
227 IEC958Context *ctx = s->priv_data;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
228
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
229 switch (s->streams[0]->codec->codec_id) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
230 case CODEC_ID_AC3:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
231 ctx->header_info = spdif_header_ac3;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
232 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
233 case CODEC_ID_MP1:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
234 case CODEC_ID_MP2:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
235 case CODEC_ID_MP3:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
236 ctx->header_info = spdif_header_mpeg;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
237 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
238 case CODEC_ID_DTS:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
239 ctx->header_info = spdif_header_dts;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
240 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
241 case CODEC_ID_AAC:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
242 ctx->header_info = spdif_header_aac;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
243 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
244 default:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
245 av_log(s, AV_LOG_ERROR, "codec not supported\n");
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
246 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
247 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
248 return 0;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
249 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
250
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
251 static int spdif_write_trailer(AVFormatContext *s)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
252 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
253 IEC958Context *ctx = s->priv_data;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
254 av_freep(&ctx->buffer);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
255 return 0;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
256 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
257
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
258 static int spdif_write_packet(struct AVFormatContext *s, AVPacket *pkt)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
259 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
260 IEC958Context *ctx = s->priv_data;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
261 int ret, padding;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
262
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
263 ctx->pkt_size = FFALIGN(pkt->size, 2) << 3;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
264 ret = ctx->header_info(s, pkt);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
265 if (ret < 0)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
266 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
267
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
268 padding = (ctx->pkt_offset - BURST_HEADER_SIZE - pkt->size) >> 1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
269 if (padding < 0) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
270 av_log(s, AV_LOG_ERROR, "bitrate is too high\n");
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
271 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
272 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
273
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
274 put_le16(s->pb, SYNCWORD1); //Pa
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
275 put_le16(s->pb, SYNCWORD2); //Pb
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
276 put_le16(s->pb, ctx->data_type); //Pc
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
277 put_le16(s->pb, ctx->pkt_size); //Pd
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
278
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
279 #if HAVE_BIGENDIAN
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
280 put_buffer(s->pb, pkt->data, pkt->size & ~1);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
281 #else
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
282 av_fast_malloc(&ctx->buffer, &ctx->buffer_size, pkt->size + FF_INPUT_BUFFER_PADDING_SIZE);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
283 if (!ctx->buffer)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
284 return AVERROR(ENOMEM);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
285 bswap_buf16((uint16_t *)ctx->buffer, (uint16_t *)pkt->data, pkt->size >> 1);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
286 put_buffer(s->pb, ctx->buffer, pkt->size & ~1);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
287 #endif
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
288
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
289 if (pkt->size & 1)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
290 put_be16(s->pb, pkt->data[pkt->size - 1]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
291
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
292 for (; padding > 0; padding--)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
293 put_be16(s->pb, 0);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
294
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
295 av_log(s, AV_LOG_DEBUG, "type=%x len=%i pkt_offset=%i\n",
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
296 ctx->data_type, pkt->size, ctx->pkt_offset);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
297
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
298 put_flush_packet(s->pb);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
299 return 0;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
300 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
301
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
302 AVOutputFormat spdif_muxer = {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
303 "spdif",
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
304 NULL_IF_CONFIG_SMALL("IEC958 - S/PDIF (IEC-61937)"),
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
305 NULL,
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
306 "spdif",
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
307 sizeof(IEC958Context),
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
308 CODEC_ID_AC3,
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
309 CODEC_ID_NONE,
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
310 spdif_write_header,
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
311 spdif_write_packet,
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
312 spdif_write_trailer,
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
313 };