annotate spdif.c @ 5747:551765b1772b libavformat

Ensure that we write clusters and blocks with known size when streaming Too many demuxers can't cope with clusters of unknown size.
author conrad
date Thu, 04 Mar 2010 08:53:14 +0000
parents ad4e3a0bd4bd
children de489de0240a
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 /**
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
23 * @file libavformat/spdif.c
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)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
64 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
65 IEC958_MPEG2_AAC_LSF_4096 = 0x13 | 0x20, ///< MPEG-2 AAC ADTS quarter-rate low sampling frequency
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
66 };
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
67
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
68 typedef struct IEC958Context {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
69 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
70 int pkt_size; ///< length code in bits
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
71 int pkt_offset; ///< data burst repetition period in bytes
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
72 uint8_t *buffer; ///< allocated buffer, used for swap bytes
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
73 int buffer_size; ///< size of allocated buffer
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
74
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
75 /// function, which generates codec dependent header information.
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
76 /// Sets data_type and data_offset
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
77 int (*header_info) (AVFormatContext *s, AVPacket *pkt);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
78 } IEC958Context;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
79
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
80 //TODO move to DSP
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
81 static void bswap_buf16(uint16_t *dst, const uint16_t *src, int w)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
82 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
83 int i;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
84
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
85 for (i = 0; i + 8 <= w; i += 8) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
86 dst[i + 0] = bswap_16(src[i + 0]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
87 dst[i + 1] = bswap_16(src[i + 1]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
88 dst[i + 2] = bswap_16(src[i + 2]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
89 dst[i + 3] = bswap_16(src[i + 3]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
90 dst[i + 4] = bswap_16(src[i + 4]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
91 dst[i + 5] = bswap_16(src[i + 5]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
92 dst[i + 6] = bswap_16(src[i + 6]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
93 dst[i + 7] = bswap_16(src[i + 7]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
94 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
95 for (; i < w; i++)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
96 dst[i + 0] = bswap_16(src[i + 0]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
97 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
98
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
99 static int spdif_header_ac3(AVFormatContext *s, AVPacket *pkt)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
100 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
101 IEC958Context *ctx = s->priv_data;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
102 int bitstream_mode = pkt->data[6] & 0x7;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
103
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
104 ctx->data_type = IEC958_AC3 | (bitstream_mode << 8);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
105 ctx->pkt_offset = AC3_FRAME_SIZE << 2;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
106 return 0;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
107 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
108
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
109 static int spdif_header_dts(AVFormatContext *s, AVPacket *pkt)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
110 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
111 IEC958Context *ctx = s->priv_data;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
112 uint32_t syncword_dts = AV_RB32(pkt->data);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
113 int blocks;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
114
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
115 switch (syncword_dts) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
116 case DCA_MARKER_RAW_BE:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
117 blocks = (AV_RB16(pkt->data + 4) >> 2) & 0x7f;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
118 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
119 case DCA_MARKER_RAW_LE:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
120 blocks = (AV_RL16(pkt->data + 4) >> 2) & 0x7f;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
121 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
122 case DCA_MARKER_14B_BE:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
123 blocks =
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
124 (((pkt->data[5] & 0x07) << 4) | ((pkt->data[6] & 0x3f) >> 2));
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_14B_LE:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
127 blocks =
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
128 (((pkt->data[4] & 0x07) << 4) | ((pkt->data[7] & 0x3f) >> 2));
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
129 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
130 default:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
131 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
132 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
133 }
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 switch (blocks) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
136 case 512 >> 5: ctx->data_type = IEC958_DTS1; break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
137 case 1024 >> 5: ctx->data_type = IEC958_DTS2; break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
138 case 2048 >> 5: ctx->data_type = IEC958_DTS3; break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
139 default:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
140 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
141 blocks << 5);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
142 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
143 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
144 ctx->pkt_offset = blocks << 7;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
145
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
146 return 0;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
147 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
148
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
149 static const enum IEC958DataType mpeg_data_type[2][3] = {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
150 // LAYER1 LAYER2 LAYER3
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
151 { 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
152 { IEC958_MPEG1_LAYER1, IEC958_MPEG1_LAYER23, IEC958_MPEG1_LAYER23 }, //MPEG1
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
153 };
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
154
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
155 static const uint16_t mpeg_pkt_offset[2][3] = {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
156 //LAYER1 LAYER2 LAYER3
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
157 { 3072, 9216, 4608 }, // MPEG2 LSF
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
158 { 1536, 4608, 4608 }, // MPEG1
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
159 };
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
160
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
161 static int spdif_header_mpeg(AVFormatContext *s, AVPacket *pkt)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
162 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
163 IEC958Context *ctx = s->priv_data;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
164 int version = (pkt->data[1] >> 3) & 3;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
165 int layer = 3 - ((pkt->data[1] >> 1) & 3);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
166 int extension = pkt->data[2] & 1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
167
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
168 if (layer == 3 || version == 1) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
169 av_log(s, AV_LOG_ERROR, "Wrong MPEG file format\n");
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
170 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
171 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
172 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
173 if (version == 2 && extension) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
174 ctx->data_type = IEC958_MPEG2_EXT;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
175 ctx->pkt_offset = 4608;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
176 } else {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
177 ctx->data_type = mpeg_data_type [version & 1][layer];
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
178 ctx->pkt_offset = mpeg_pkt_offset[version & 1][layer];
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
179 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
180 // TODO Data type dependant info (normal/karaoke, dynamic range control)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
181 return 0;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
182 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
183
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
184 static int spdif_header_aac(AVFormatContext *s, AVPacket *pkt)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
185 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
186 IEC958Context *ctx = s->priv_data;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
187 AACADTSHeaderInfo hdr;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
188 GetBitContext gbc;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
189 int ret;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
190
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
191 init_get_bits(&gbc, pkt->data, AAC_ADTS_HEADER_SIZE * 8);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
192 ret = ff_aac_parse_header(&gbc, &hdr);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
193 if (ret < 0) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
194 av_log(s, AV_LOG_ERROR, "Wrong AAC file format\n");
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
195 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
196 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
197
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
198 ctx->pkt_offset = hdr.samples << 2;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
199 switch (hdr.num_aac_frames) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
200 case 1:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
201 ctx->data_type = IEC958_MPEG2_AAC;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
202 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
203 case 2:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
204 ctx->data_type = IEC958_MPEG2_AAC_LSF_2048;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
205 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
206 case 4:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
207 ctx->data_type = IEC958_MPEG2_AAC_LSF_4096;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
208 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
209 default:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
210 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
211 hdr.samples);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
212 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
213 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
214 //TODO Data type dependent info (LC profile/SBR)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
215 return 0;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
216 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
217
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
218 static int spdif_write_header(AVFormatContext *s)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
219 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
220 IEC958Context *ctx = s->priv_data;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
221
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
222 switch (s->streams[0]->codec->codec_id) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
223 case CODEC_ID_AC3:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
224 ctx->header_info = spdif_header_ac3;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
225 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
226 case CODEC_ID_MP1:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
227 case CODEC_ID_MP2:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
228 case CODEC_ID_MP3:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
229 ctx->header_info = spdif_header_mpeg;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
230 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
231 case CODEC_ID_DTS:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
232 ctx->header_info = spdif_header_dts;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
233 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
234 case CODEC_ID_AAC:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
235 ctx->header_info = spdif_header_aac;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
236 break;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
237 default:
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
238 av_log(s, AV_LOG_ERROR, "codec not supported\n");
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
239 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
240 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
241 put_le16(s->pb, 0);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
242 put_le16(s->pb, 0);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
243 put_le16(s->pb, 0);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
244 put_le16(s->pb, 0);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
245 return 0;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
246 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
247
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
248 static int spdif_write_trailer(AVFormatContext *s)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
249 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
250 IEC958Context *ctx = s->priv_data;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
251 av_freep(&ctx->buffer);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
252 return 0;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
253 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
254
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
255 static int spdif_write_packet(struct AVFormatContext *s, AVPacket *pkt)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
256 {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
257 IEC958Context *ctx = s->priv_data;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
258 int ret, padding;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
259
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
260 ctx->pkt_size = FFALIGN(pkt->size, 2) << 3;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
261 ret = ctx->header_info(s, pkt);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
262 if (ret < 0)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
263 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
264
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
265 padding = (ctx->pkt_offset - BURST_HEADER_SIZE - pkt->size) >> 1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
266 if (padding < 0) {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
267 av_log(s, AV_LOG_ERROR, "bitrate is too high\n");
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
268 return -1;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
269 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
270
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
271 put_le16(s->pb, SYNCWORD1); //Pa
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
272 put_le16(s->pb, SYNCWORD2); //Pb
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
273 put_le16(s->pb, ctx->data_type); //Pc
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
274 put_le16(s->pb, ctx->pkt_size); //Pd
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
275
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
276 #if HAVE_BIGENDIAN
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
277 put_buffer(s->pb, pkt->data, pkt->size & ~1);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
278 #else
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
279 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
280 if (!ctx->buffer)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
281 return AVERROR(ENOMEM);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
282 bswap_buf16((uint16_t *)ctx->buffer, (uint16_t *)pkt->data, pkt->size >> 1);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
283 put_buffer(s->pb, ctx->buffer, pkt->size & ~1);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
284 #endif
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
285
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
286 if (pkt->size & 1)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
287 put_be16(s->pb, pkt->data[pkt->size - 1]);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
288
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
289 for (; padding > 0; padding--)
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
290 put_be16(s->pb, 0);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
291
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
292 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
293 ctx->data_type, pkt->size, ctx->pkt_offset);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
294
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
295 put_flush_packet(s->pb);
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
296 return 0;
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
297 }
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
298
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
299 AVOutputFormat spdif_muxer = {
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
300 "spdif",
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
301 NULL_IF_CONFIG_SMALL("IEC958 - S/PDIF (IEC-61937)"),
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
302 NULL,
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 sizeof(IEC958Context),
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
305 CODEC_ID_AC3,
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
306 CODEC_ID_NONE,
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
307 spdif_write_header,
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
308 spdif_write_packet,
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
309 spdif_write_trailer,
ad4e3a0bd4bd Add support for S/PDIF encapsulation.
bwolowiec
parents:
diff changeset
310 };