1 | /*
|
---|
2 | * General DV muxer/demuxer
|
---|
3 | * Copyright (c) 2003 Roman Shaposhnik
|
---|
4 | *
|
---|
5 | * Many thanks to Dan Dennedy <[email protected]> for providing wealth
|
---|
6 | * of DV technical info.
|
---|
7 | *
|
---|
8 | * Raw DV format
|
---|
9 | * Copyright (c) 2002 Fabrice Bellard.
|
---|
10 | *
|
---|
11 | * 50 Mbps (DVCPRO50) support
|
---|
12 | * Copyright (c) 2006 Daniel Maas <[email protected]>
|
---|
13 | *
|
---|
14 | * This library is free software; you can redistribute it and/or
|
---|
15 | * modify it under the terms of the GNU Lesser General Public
|
---|
16 | * License as published by the Free Software Foundation; either
|
---|
17 | * version 2 of the License, or (at your option) any later version.
|
---|
18 | *
|
---|
19 | * This library is distributed in the hope that it will be useful,
|
---|
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
22 | * Lesser General Public License for more details.
|
---|
23 | *
|
---|
24 | * You should have received a copy of the GNU Lesser General Public
|
---|
25 | * License along with this library; if not, write to the Free Software
|
---|
26 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
---|
27 | */
|
---|
28 | #include <time.h>
|
---|
29 | #include "avformat.h"
|
---|
30 | #include "dvdata.h"
|
---|
31 | #include "dv.h"
|
---|
32 |
|
---|
33 | struct DVDemuxContext {
|
---|
34 | const DVprofile* sys; /* Current DV profile. E.g.: 525/60, 625/50 */
|
---|
35 | AVFormatContext* fctx;
|
---|
36 | AVStream* vst;
|
---|
37 | AVStream* ast[2];
|
---|
38 | AVPacket audio_pkt[2];
|
---|
39 | uint8_t audio_buf[2][8192];
|
---|
40 | int ach;
|
---|
41 | int frames;
|
---|
42 | uint64_t abytes;
|
---|
43 | };
|
---|
44 |
|
---|
45 | struct DVMuxContext {
|
---|
46 | const DVprofile* sys; /* Current DV profile. E.g.: 525/60, 625/50 */
|
---|
47 | int n_ast; /* Number of stereo audio streams (up to 2) */
|
---|
48 | AVStream *ast[2]; /* Stereo audio streams */
|
---|
49 | FifoBuffer audio_data[2]; /* Fifo for storing excessive amounts of PCM */
|
---|
50 | int frames; /* Number of a current frame */
|
---|
51 | time_t start_time; /* Start time of recording */
|
---|
52 | uint8_t aspect; /* Aspect ID 0 - 4:3, 7 - 16:9 */
|
---|
53 | int has_audio; /* frame under contruction has audio */
|
---|
54 | int has_video; /* frame under contruction has video */
|
---|
55 | uint8_t frame_buf[DV_MAX_FRAME_SIZE]; /* frame under contruction */
|
---|
56 | };
|
---|
57 |
|
---|
58 | enum dv_section_type {
|
---|
59 | dv_sect_header = 0x1f,
|
---|
60 | dv_sect_subcode = 0x3f,
|
---|
61 | dv_sect_vaux = 0x56,
|
---|
62 | dv_sect_audio = 0x76,
|
---|
63 | dv_sect_video = 0x96,
|
---|
64 | };
|
---|
65 |
|
---|
66 | enum dv_pack_type {
|
---|
67 | dv_header525 = 0x3f, /* see dv_write_pack for important details on */
|
---|
68 | dv_header625 = 0xbf, /* these two packs */
|
---|
69 | dv_timecode = 0x13,
|
---|
70 | dv_audio_source = 0x50,
|
---|
71 | dv_audio_control = 0x51,
|
---|
72 | dv_audio_recdate = 0x52,
|
---|
73 | dv_audio_rectime = 0x53,
|
---|
74 | dv_video_source = 0x60,
|
---|
75 | dv_video_control = 0x61,
|
---|
76 | dv_video_recdate = 0x62,
|
---|
77 | dv_video_rectime = 0x63,
|
---|
78 | dv_unknown_pack = 0xff,
|
---|
79 | };
|
---|
80 |
|
---|
81 |
|
---|
82 |
|
---|
83 | /*
|
---|
84 | * The reason why the following three big ugly looking tables are
|
---|
85 | * here is my lack of DV spec IEC 61834. The tables were basically
|
---|
86 | * constructed to make code that places packs in SSYB, VAUX and
|
---|
87 | * AAUX blocks very simple and table-driven. They conform to the
|
---|
88 | * SMPTE 314M and the output of my personal DV camcorder, neither
|
---|
89 | * of which is sufficient for a reliable DV stream producing. Thus
|
---|
90 | * while code is still in development I'll be gathering input from
|
---|
91 | * people with different DV equipment and modifying the tables to
|
---|
92 | * accommodate all the quirks. Later on, if possible, some of them
|
---|
93 | * will be folded into smaller tables and/or switch-if logic. For
|
---|
94 | * now, my only excuse is -- they don't eat up that much of a space.
|
---|
95 | */
|
---|
96 |
|
---|
97 | static const int dv_ssyb_packs_dist[12][6] = {
|
---|
98 | { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },
|
---|
99 | { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },
|
---|
100 | { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },
|
---|
101 | { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },
|
---|
102 | { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },
|
---|
103 | { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },
|
---|
104 | { 0x13, 0x62, 0x63, 0x13, 0x62, 0x63 },
|
---|
105 | { 0x13, 0x62, 0x63, 0x13, 0x62, 0x63 },
|
---|
106 | { 0x13, 0x62, 0x63, 0x13, 0x62, 0x63 },
|
---|
107 | { 0x13, 0x62, 0x63, 0x13, 0x62, 0x63 },
|
---|
108 | { 0x13, 0x62, 0x63, 0x13, 0x62, 0x63 },
|
---|
109 | { 0x13, 0x62, 0x63, 0x13, 0x62, 0x63 },
|
---|
110 | };
|
---|
111 |
|
---|
112 | static const int dv_vaux_packs_dist[12][15] = {
|
---|
113 | { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,
|
---|
114 | 0x60, 0x61, 0x62, 0x63, 0xff, 0xff },
|
---|
115 | { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,
|
---|
116 | 0x60, 0x61, 0x62, 0x63, 0xff, 0xff },
|
---|
117 | { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,
|
---|
118 | 0x60, 0x61, 0x62, 0x63, 0xff, 0xff },
|
---|
119 | { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,
|
---|
120 | 0x60, 0x61, 0x62, 0x63, 0xff, 0xff },
|
---|
121 | { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,
|
---|
122 | 0x60, 0x61, 0x62, 0x63, 0xff, 0xff },
|
---|
123 | { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,
|
---|
124 | 0x60, 0x61, 0x62, 0x63, 0xff, 0xff },
|
---|
125 | { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,
|
---|
126 | 0x60, 0x61, 0x62, 0x63, 0xff, 0xff },
|
---|
127 | { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,
|
---|
128 | 0x60, 0x61, 0x62, 0x63, 0xff, 0xff },
|
---|
129 | { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,
|
---|
130 | 0x60, 0x61, 0x62, 0x63, 0xff, 0xff },
|
---|
131 | { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,
|
---|
132 | 0x60, 0x61, 0x62, 0x63, 0xff, 0xff },
|
---|
133 | { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,
|
---|
134 | 0x60, 0x61, 0x62, 0x63, 0xff, 0xff },
|
---|
135 | { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,
|
---|
136 | 0x60, 0x61, 0x62, 0x63, 0xff, 0xff },
|
---|
137 | };
|
---|
138 |
|
---|
139 | static const int dv_aaux_packs_dist[12][9] = {
|
---|
140 | { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
|
---|
141 | { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
|
---|
142 | { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
|
---|
143 | { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
|
---|
144 | { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
|
---|
145 | { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
|
---|
146 | { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
|
---|
147 | { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
|
---|
148 | { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
|
---|
149 | { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
|
---|
150 | { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
|
---|
151 | { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
|
---|
152 | };
|
---|
153 |
|
---|
154 | static inline uint16_t dv_audio_12to16(uint16_t sample)
|
---|
155 | {
|
---|
156 | uint16_t shift, result;
|
---|
157 |
|
---|
158 | sample = (sample < 0x800) ? sample : sample | 0xf000;
|
---|
159 | shift = (sample & 0xf00) >> 8;
|
---|
160 |
|
---|
161 | if (shift < 0x2 || shift > 0xd) {
|
---|
162 | result = sample;
|
---|
163 | } else if (shift < 0x8) {
|
---|
164 | shift--;
|
---|
165 | result = (sample - (256 * shift)) << shift;
|
---|
166 | } else {
|
---|
167 | shift = 0xe - shift;
|
---|
168 | result = ((sample + ((256 * shift) + 1)) << shift) - 1;
|
---|
169 | }
|
---|
170 |
|
---|
171 | return result;
|
---|
172 | }
|
---|
173 |
|
---|
174 | static int dv_audio_frame_size(const DVprofile* sys, int frame)
|
---|
175 | {
|
---|
176 | return sys->audio_samples_dist[frame % (sizeof(sys->audio_samples_dist)/
|
---|
177 | sizeof(sys->audio_samples_dist[0]))];
|
---|
178 | }
|
---|
179 |
|
---|
180 | static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* buf)
|
---|
181 | {
|
---|
182 | struct tm tc;
|
---|
183 | time_t ct;
|
---|
184 | int ltc_frame;
|
---|
185 |
|
---|
186 | /* Its hard to tell what SMPTE requires w.r.t. APT, but Quicktime needs it.
|
---|
187 | * We set it based on pix_fmt value but it really should be per DV profile */
|
---|
188 | int apt = (c->sys->pix_fmt == PIX_FMT_YUV422P ? 1 : 0);
|
---|
189 |
|
---|
190 | buf[0] = (uint8_t)pack_id;
|
---|
191 | switch (pack_id) {
|
---|
192 | case dv_header525: /* I can't imagine why these two weren't defined as real */
|
---|
193 | case dv_header625: /* packs in SMPTE314M -- they definitely look like ones */
|
---|
194 | buf[1] = 0xf8 | /* reserved -- always 1 */
|
---|
195 | (apt & 0x07); /* APT: Track application ID */
|
---|
196 | buf[2] = (0 << 7) | /* TF1: audio data is 0 - valid; 1 - invalid */
|
---|
197 | (0x0f << 3) | /* reserved -- always 1 */
|
---|
198 | (apt & 0x07); /* AP1: Audio application ID */
|
---|
199 | buf[3] = (0 << 7) | /* TF2: video data is 0 - valid; 1 - invalid */
|
---|
200 | (0x0f << 3) | /* reserved -- always 1 */
|
---|
201 | (apt & 0x07); /* AP2: Video application ID */
|
---|
202 | buf[4] = (0 << 7) | /* TF3: subcode(SSYB) is 0 - valid; 1 - invalid */
|
---|
203 | (0x0f << 3) | /* reserved -- always 1 */
|
---|
204 | (apt & 0x07); /* AP3: Subcode application ID */
|
---|
205 | break;
|
---|
206 | case dv_timecode:
|
---|
207 | ct = (time_t)(c->frames / ((float)c->sys->frame_rate /
|
---|
208 | (float)c->sys->frame_rate_base));
|
---|
209 | brktimegm(ct, &tc);
|
---|
210 | /*
|
---|
211 | * LTC drop-frame frame counter drops two frames (0 and 1) every
|
---|
212 | * minute, unless it is exactly divisible by 10
|
---|
213 | */
|
---|
214 | ltc_frame = (c->frames + 2*ct/60 - 2*ct/600) % c->sys->ltc_divisor;
|
---|
215 | buf[1] = (0 << 7) | /* Color fame: 0 - unsync; 1 - sync mode */
|
---|
216 | (1 << 6) | /* Drop frame timecode: 0 - nondrop; 1 - drop */
|
---|
217 | ((ltc_frame / 10) << 4) | /* Tens of frames */
|
---|
218 | (ltc_frame % 10); /* Units of frames */
|
---|
219 | buf[2] = (1 << 7) | /* Biphase mark polarity correction: 0 - even; 1 - odd */
|
---|
220 | ((tc.tm_sec / 10) << 4) | /* Tens of seconds */
|
---|
221 | (tc.tm_sec % 10); /* Units of seconds */
|
---|
222 | buf[3] = (1 << 7) | /* Binary group flag BGF0 */
|
---|
223 | ((tc.tm_min / 10) << 4) | /* Tens of minutes */
|
---|
224 | (tc.tm_min % 10); /* Units of minutes */
|
---|
225 | buf[4] = (1 << 7) | /* Binary group flag BGF2 */
|
---|
226 | (1 << 6) | /* Binary group flag BGF1 */
|
---|
227 | ((tc.tm_hour / 10) << 4) | /* Tens of hours */
|
---|
228 | (tc.tm_hour % 10); /* Units of hours */
|
---|
229 | break;
|
---|
230 | case dv_audio_source: /* AAUX source pack */
|
---|
231 | buf[1] = (0 << 7) | /* locked mode */
|
---|
232 | (1 << 6) | /* reserved -- always 1 */
|
---|
233 | (dv_audio_frame_size(c->sys, c->frames) -
|
---|
234 | c->sys->audio_min_samples[0]);
|
---|
235 | /* # of samples */
|
---|
236 | buf[2] = (0 << 7) | /* multi-stereo */
|
---|
237 | (0 << 5) | /* #of audio channels per block: 0 -- 1 channel */
|
---|
238 | (0 << 4) | /* pair bit: 0 -- one pair of channels */
|
---|
239 | 0; /* audio mode */
|
---|
240 | buf[3] = (1 << 7) | /* res */
|
---|
241 | (1 << 6) | /* multi-language flag */
|
---|
242 | (c->sys->dsf << 5) | /* system: 60fields/50fields */
|
---|
243 | (apt << 1);/* definition: 0 -- 25Mbps, 2 -- 50Mbps */
|
---|
244 | buf[4] = (1 << 7) | /* emphasis: 1 -- off */
|
---|
245 | (0 << 6) | /* emphasis time constant: 0 -- reserved */
|
---|
246 | (0 << 3) | /* frequency: 0 -- 48Khz, 1 -- 44,1Khz, 2 -- 32Khz */
|
---|
247 | 0; /* quantization: 0 -- 16bit linear, 1 -- 12bit nonlinear */
|
---|
248 | break;
|
---|
249 | case dv_audio_control:
|
---|
250 | buf[1] = (0 << 6) | /* copy protection: 0 -- unrestricted */
|
---|
251 | (1 << 4) | /* input source: 1 -- digital input */
|
---|
252 | (3 << 2) | /* compression: 3 -- no information */
|
---|
253 | 0; /* misc. info/SMPTE emphasis off */
|
---|
254 | buf[2] = (1 << 7) | /* recording start point: 1 -- no */
|
---|
255 | (1 << 6) | /* recording end point: 1 -- no */
|
---|
256 | (1 << 3) | /* recording mode: 1 -- original */
|
---|
257 | 7;
|
---|
258 | buf[3] = (1 << 7) | /* direction: 1 -- forward */
|
---|
259 | 0x20; /* speed */
|
---|
260 | buf[4] = (1 << 7) | /* reserved -- always 1 */
|
---|
261 | 0x7f; /* genre category */
|
---|
262 | break;
|
---|
263 | case dv_audio_recdate:
|
---|
264 | case dv_video_recdate: /* VAUX recording date */
|
---|
265 | ct = c->start_time + (time_t)(c->frames /
|
---|
266 | ((float)c->sys->frame_rate / (float)c->sys->frame_rate_base));
|
---|
267 | brktimegm(ct, &tc);
|
---|
268 | buf[1] = 0xff; /* ds, tm, tens of time zone, units of time zone */
|
---|
269 | /* 0xff is very likely to be "unknown" */
|
---|
270 | buf[2] = (3 << 6) | /* reserved -- always 1 */
|
---|
271 | ((tc.tm_mday / 10) << 4) | /* Tens of day */
|
---|
272 | (tc.tm_mday % 10); /* Units of day */
|
---|
273 | buf[3] = /* we set high 4 bits to 0, shouldn't we set them to week? */
|
---|
274 | ((tc.tm_mon / 10) << 4) | /* Tens of month */
|
---|
275 | (tc.tm_mon % 10); /* Units of month */
|
---|
276 | buf[4] = (((tc.tm_year % 100) / 10) << 4) | /* Tens of year */
|
---|
277 | (tc.tm_year % 10); /* Units of year */
|
---|
278 | break;
|
---|
279 | case dv_audio_rectime: /* AAUX recording time */
|
---|
280 | case dv_video_rectime: /* VAUX recording time */
|
---|
281 | ct = c->start_time + (time_t)(c->frames /
|
---|
282 | ((float)c->sys->frame_rate / (float)c->sys->frame_rate_base));
|
---|
283 | brktimegm(ct, &tc);
|
---|
284 | buf[1] = (3 << 6) | /* reserved -- always 1 */
|
---|
285 | 0x3f; /* tens of frame, units of frame: 0x3f - "unknown" ? */
|
---|
286 | buf[2] = (1 << 7) | /* reserved -- always 1 */
|
---|
287 | ((tc.tm_sec / 10) << 4) | /* Tens of seconds */
|
---|
288 | (tc.tm_sec % 10); /* Units of seconds */
|
---|
289 | buf[3] = (1 << 7) | /* reserved -- always 1 */
|
---|
290 | ((tc.tm_min / 10) << 4) | /* Tens of minutes */
|
---|
291 | (tc.tm_min % 10); /* Units of minutes */
|
---|
292 | buf[4] = (3 << 6) | /* reserved -- always 1 */
|
---|
293 | ((tc.tm_hour / 10) << 4) | /* Tens of hours */
|
---|
294 | (tc.tm_hour % 10); /* Units of hours */
|
---|
295 | break;
|
---|
296 | case dv_video_source:
|
---|
297 | buf[1] = 0xff; /* reserved -- always 1 */
|
---|
298 | buf[2] = (1 << 7) | /* B/W: 0 - b/w, 1 - color */
|
---|
299 | (1 << 6) | /* following CLF is valid - 0, invalid - 1 */
|
---|
300 | (3 << 4) | /* CLF: color frames id (see ITU-R BT.470-4) */
|
---|
301 | 0xf; /* reserved -- always 1 */
|
---|
302 | buf[3] = (3 << 6) | /* reserved -- always 1 */
|
---|
303 | (c->sys->dsf << 5) | /* system: 60fields/50fields */
|
---|
304 | (apt << 2); /* signal type video compression */
|
---|
305 | buf[4] = 0xff; /* VISC: 0xff -- no information */
|
---|
306 | break;
|
---|
307 | case dv_video_control:
|
---|
308 | buf[1] = (0 << 6) | /* Copy generation management (CGMS) 0 -- free */
|
---|
309 | 0x3f; /* reserved -- always 1 */
|
---|
310 | buf[2] = 0xc8 | /* reserved -- always b11001xxx */
|
---|
311 | c->aspect;
|
---|
312 | buf[3] = (1 << 7) | /* Frame/field flag 1 -- frame, 0 -- field */
|
---|
313 | (1 << 6) | /* First/second field flag 0 -- field 2, 1 -- field 1 */
|
---|
314 | (1 << 5) | /* Frame change flag 0 -- same picture as before, 1 -- different */
|
---|
315 | (1 << 4) | /* 1 - interlaced, 0 - noninterlaced */
|
---|
316 | 0xc; /* reserved -- always b1100 */
|
---|
317 | buf[4] = 0xff; /* reserved -- always 1 */
|
---|
318 | break;
|
---|
319 | default:
|
---|
320 | buf[1] = buf[2] = buf[3] = buf[4] = 0xff;
|
---|
321 | }
|
---|
322 | return 5;
|
---|
323 | }
|
---|
324 |
|
---|
325 | static inline int dv_write_dif_id(enum dv_section_type t, uint8_t chan_num, uint8_t seq_num,
|
---|
326 | uint8_t dif_num, uint8_t* buf)
|
---|
327 | {
|
---|
328 | buf[0] = (uint8_t)t; /* Section type */
|
---|
329 | buf[1] = (seq_num<<4) | /* DIF seq number 0-9 for 525/60; 0-11 for 625/50 */
|
---|
330 | (chan_num << 3) | /* FSC: for 50Mb/s 0 - first channel; 1 - second */
|
---|
331 | 7; /* reserved -- always 1 */
|
---|
332 | buf[2] = dif_num; /* DIF block number Video: 0-134, Audio: 0-8 */
|
---|
333 | return 3;
|
---|
334 | }
|
---|
335 |
|
---|
336 | static inline int dv_write_ssyb_id(uint8_t syb_num, uint8_t fr, uint8_t* buf)
|
---|
337 | {
|
---|
338 | if (syb_num == 0 || syb_num == 6) {
|
---|
339 | buf[0] = (fr<<7) | /* FR ID 1 - first half of each channel; 0 - second */
|
---|
340 | (0<<4) | /* AP3 (Subcode application ID) */
|
---|
341 | 0x0f; /* reserved -- always 1 */
|
---|
342 | }
|
---|
343 | else if (syb_num == 11) {
|
---|
344 | buf[0] = (fr<<7) | /* FR ID 1 - first half of each channel; 0 - second */
|
---|
345 | 0x7f; /* reserved -- always 1 */
|
---|
346 | }
|
---|
347 | else {
|
---|
348 | buf[0] = (fr<<7) | /* FR ID 1 - first half of each channel; 0 - second */
|
---|
349 | (0<<4) | /* APT (Track application ID) */
|
---|
350 | 0x0f; /* reserved -- always 1 */
|
---|
351 | }
|
---|
352 | buf[1] = 0xf0 | /* reserved -- always 1 */
|
---|
353 | (syb_num & 0x0f); /* SSYB number 0 - 11 */
|
---|
354 | buf[2] = 0xff; /* reserved -- always 1 */
|
---|
355 | return 3;
|
---|
356 | }
|
---|
357 |
|
---|
358 | static void dv_format_frame(DVMuxContext *c, uint8_t* buf)
|
---|
359 | {
|
---|
360 | int chan, i, j, k;
|
---|
361 |
|
---|
362 | for (chan = 0; chan < c->sys->n_difchan; chan++) {
|
---|
363 | for (i = 0; i < c->sys->difseg_size; i++) {
|
---|
364 | memset(buf, 0xff, 80 * 6); /* First 6 DIF blocks are for control data */
|
---|
365 |
|
---|
366 | /* DV header: 1DIF */
|
---|
367 | buf += dv_write_dif_id(dv_sect_header, chan, i, 0, buf);
|
---|
368 | buf += dv_write_pack((c->sys->dsf ? dv_header625 : dv_header525), c, buf);
|
---|
369 | buf += 72; /* unused bytes */
|
---|
370 |
|
---|
371 | /* DV subcode: 2DIFs */
|
---|
372 | for (j = 0; j < 2; j++) {
|
---|
373 | buf += dv_write_dif_id(dv_sect_subcode, chan, i, j, buf);
|
---|
374 | for (k = 0; k < 6; k++) {
|
---|
375 | buf += dv_write_ssyb_id(k, (i < c->sys->difseg_size/2), buf);
|
---|
376 | buf += dv_write_pack(dv_ssyb_packs_dist[i][k], c, buf);
|
---|
377 | }
|
---|
378 | buf += 29; /* unused bytes */
|
---|
379 | }
|
---|
380 |
|
---|
381 | /* DV VAUX: 3DIFs */
|
---|
382 | for (j = 0; j < 3; j++) {
|
---|
383 | buf += dv_write_dif_id(dv_sect_vaux, chan, i, j, buf);
|
---|
384 | for (k = 0; k < 15 ; k++)
|
---|
385 | buf += dv_write_pack(dv_vaux_packs_dist[i][k], c, buf);
|
---|
386 | buf += 2; /* unused bytes */
|
---|
387 | }
|
---|
388 |
|
---|
389 | /* DV Audio/Video: 135 Video DIFs + 9 Audio DIFs */
|
---|
390 | for (j = 0; j < 135; j++) {
|
---|
391 | if (j%15 == 0) {
|
---|
392 | memset(buf, 0xff, 80);
|
---|
393 | buf += dv_write_dif_id(dv_sect_audio, chan, i, j/15, buf);
|
---|
394 | buf += 77; /* audio control & shuffled PCM audio */
|
---|
395 | }
|
---|
396 | buf += dv_write_dif_id(dv_sect_video, chan, i, j, buf);
|
---|
397 | buf += 77; /* 1 video macro block: 1 bytes control
|
---|
398 | 4 * 14 bytes Y 8x8 data
|
---|
399 | 10 bytes Cr 8x8 data
|
---|
400 | 10 bytes Cb 8x8 data */
|
---|
401 | }
|
---|
402 | }
|
---|
403 | }
|
---|
404 | }
|
---|
405 |
|
---|
406 | static void dv_inject_audio(DVMuxContext *c, const uint8_t* pcm, int channel, uint8_t* frame_ptr)
|
---|
407 | {
|
---|
408 | int i, j, d, of, size;
|
---|
409 | size = 4 * dv_audio_frame_size(c->sys, c->frames);
|
---|
410 | frame_ptr += channel * c->sys->difseg_size * 150 * 80;
|
---|
411 | for (i = 0; i < c->sys->difseg_size; i++) {
|
---|
412 | frame_ptr += 6 * 80; /* skip DIF segment header */
|
---|
413 | for (j = 0; j < 9; j++) {
|
---|
414 | dv_write_pack(dv_aaux_packs_dist[i][j], c, &frame_ptr[3]);
|
---|
415 | for (d = 8; d < 80; d+=2) {
|
---|
416 | of = c->sys->audio_shuffle[i][j] + (d - 8)/2 * c->sys->audio_stride;
|
---|
417 | if (of*2 >= size)
|
---|
418 | continue;
|
---|
419 |
|
---|
420 | frame_ptr[d] = pcm[of*2+1]; // FIXME: may be we have to admit
|
---|
421 | frame_ptr[d+1] = pcm[of*2]; // that DV is a big endian PCM
|
---|
422 | }
|
---|
423 | frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */
|
---|
424 | }
|
---|
425 | }
|
---|
426 | }
|
---|
427 |
|
---|
428 | static void dv_inject_video(DVMuxContext *c, const uint8_t* video_data, uint8_t* frame_ptr)
|
---|
429 | {
|
---|
430 | int chan, i, j;
|
---|
431 | int ptr = 0;
|
---|
432 |
|
---|
433 | for (chan = 0; chan < c->sys->n_difchan; chan++) {
|
---|
434 | for (i = 0; i < c->sys->difseg_size; i++) {
|
---|
435 | ptr += 6 * 80; /* skip DIF segment header */
|
---|
436 | for (j = 0; j < 135; j++) {
|
---|
437 | if (j%15 == 0)
|
---|
438 | ptr += 80; /* skip Audio DIF */
|
---|
439 | ptr += 3;
|
---|
440 | memcpy(frame_ptr + ptr, video_data + ptr, 77);
|
---|
441 | ptr += 77;
|
---|
442 | }
|
---|
443 | }
|
---|
444 | }
|
---|
445 | }
|
---|
446 |
|
---|
447 | /*
|
---|
448 | * This is the dumbest implementation of all -- it simply looks at
|
---|
449 | * a fixed offset and if pack isn't there -- fails. We might want
|
---|
450 | * to have a fallback mechanism for complete search of missing packs.
|
---|
451 | */
|
---|
452 | static const uint8_t* dv_extract_pack(uint8_t* frame, enum dv_pack_type t)
|
---|
453 | {
|
---|
454 | int offs;
|
---|
455 |
|
---|
456 | switch (t) {
|
---|
457 | case dv_audio_source:
|
---|
458 | offs = (80*6 + 80*16*3 + 3);
|
---|
459 | break;
|
---|
460 | case dv_audio_control:
|
---|
461 | offs = (80*6 + 80*16*4 + 3);
|
---|
462 | break;
|
---|
463 | case dv_video_control:
|
---|
464 | offs = (80*5 + 48 + 5);
|
---|
465 | break;
|
---|
466 | default:
|
---|
467 | return NULL;
|
---|
468 | }
|
---|
469 |
|
---|
470 | return (frame[offs] == t ? &frame[offs] : NULL);
|
---|
471 | }
|
---|
472 |
|
---|
473 | /*
|
---|
474 | * There's a couple of assumptions being made here:
|
---|
475 | * 1. By default we silence erroneous (0x8000/16bit 0x800/12bit) audio samples.
|
---|
476 | * We can pass them upwards when ffmpeg will be ready to deal with them.
|
---|
477 | * 2. We don't do software emphasis.
|
---|
478 | * 3. Audio is always returned as 16bit linear samples: 12bit nonlinear samples
|
---|
479 | * are converted into 16bit linear ones.
|
---|
480 | */
|
---|
481 | static int dv_extract_audio(uint8_t* frame, uint8_t* pcm, uint8_t* pcm2,
|
---|
482 | const DVprofile *sys)
|
---|
483 | {
|
---|
484 | int size, chan, i, j, d, of, smpls, freq, quant, half_ch;
|
---|
485 | uint16_t lc, rc;
|
---|
486 | const uint8_t* as_pack;
|
---|
487 |
|
---|
488 | as_pack = dv_extract_pack(frame, dv_audio_source);
|
---|
489 | if (!as_pack) /* No audio ? */
|
---|
490 | return 0;
|
---|
491 |
|
---|
492 | smpls = as_pack[1] & 0x3f; /* samples in this frame - min. samples */
|
---|
493 | freq = (as_pack[4] >> 3) & 0x07; /* 0 - 48KHz, 1 - 44,1kHz, 2 - 32 kHz */
|
---|
494 | quant = as_pack[4] & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */
|
---|
495 |
|
---|
496 | if (quant > 1)
|
---|
497 | return -1; /* Unsupported quantization */
|
---|
498 |
|
---|
499 | size = (sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */
|
---|
500 | half_ch = sys->difseg_size/2;
|
---|
501 |
|
---|
502 | /* for each DIF channel */
|
---|
503 | for (chan = 0; chan < sys->n_difchan; chan++) {
|
---|
504 | /* for each DIF segment */
|
---|
505 | for (i = 0; i < sys->difseg_size; i++) {
|
---|
506 | frame += 6 * 80; /* skip DIF segment header */
|
---|
507 | if (quant == 1 && i == half_ch) {
|
---|
508 | /* next stereo channel (12bit mode only) */
|
---|
509 | if (!pcm2)
|
---|
510 | break;
|
---|
511 | else
|
---|
512 | pcm = pcm2;
|
---|
513 | }
|
---|
514 |
|
---|
515 | /* for each AV sequence */
|
---|
516 | for (j = 0; j < 9; j++) {
|
---|
517 | for (d = 8; d < 80; d += 2) {
|
---|
518 | if (quant == 0) { /* 16bit quantization */
|
---|
519 | of = sys->audio_shuffle[i][j] + (d - 8)/2 * sys->audio_stride;
|
---|
520 | if (of*2 >= size)
|
---|
521 | continue;
|
---|
522 |
|
---|
523 | pcm[of*2] = frame[d+1]; // FIXME: may be we have to admit
|
---|
524 | pcm[of*2+1] = frame[d]; // that DV is a big endian PCM
|
---|
525 | if (pcm[of*2+1] == 0x80 && pcm[of*2] == 0x00)
|
---|
526 | pcm[of*2+1] = 0;
|
---|
527 | } else { /* 12bit quantization */
|
---|
528 | lc = ((uint16_t)frame[d] << 4) |
|
---|
529 | ((uint16_t)frame[d+2] >> 4);
|
---|
530 | rc = ((uint16_t)frame[d+1] << 4) |
|
---|
531 | ((uint16_t)frame[d+2] & 0x0f);
|
---|
532 | lc = (lc == 0x800 ? 0 : dv_audio_12to16(lc));
|
---|
533 | rc = (rc == 0x800 ? 0 : dv_audio_12to16(rc));
|
---|
534 |
|
---|
535 | of = sys->audio_shuffle[i%half_ch][j] + (d - 8)/3 * sys->audio_stride;
|
---|
536 | if (of*2 >= size)
|
---|
537 | continue;
|
---|
538 |
|
---|
539 | pcm[of*2] = lc & 0xff; // FIXME: may be we have to admit
|
---|
540 | pcm[of*2+1] = lc >> 8; // that DV is a big endian PCM
|
---|
541 | of = sys->audio_shuffle[i%half_ch+half_ch][j] +
|
---|
542 | (d - 8)/3 * sys->audio_stride;
|
---|
543 | pcm[of*2] = rc & 0xff; // FIXME: may be we have to admit
|
---|
544 | pcm[of*2+1] = rc >> 8; // that DV is a big endian PCM
|
---|
545 | ++d;
|
---|
546 | }
|
---|
547 | }
|
---|
548 |
|
---|
549 | frame += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */
|
---|
550 | }
|
---|
551 | }
|
---|
552 |
|
---|
553 | /* next stereo channel (50Mbps only) */
|
---|
554 | if(!pcm2)
|
---|
555 | break;
|
---|
556 | pcm = pcm2;
|
---|
557 | }
|
---|
558 |
|
---|
559 | return size;
|
---|
560 | }
|
---|
561 |
|
---|
562 | static int dv_extract_audio_info(DVDemuxContext* c, uint8_t* frame)
|
---|
563 | {
|
---|
564 | const uint8_t* as_pack;
|
---|
565 | int freq, stype, smpls, quant, i, ach;
|
---|
566 |
|
---|
567 | as_pack = dv_extract_pack(frame, dv_audio_source);
|
---|
568 | if (!as_pack || !c->sys) { /* No audio ? */
|
---|
569 | c->ach = 0;
|
---|
570 | return 0;
|
---|
571 | }
|
---|
572 |
|
---|
573 | smpls = as_pack[1] & 0x3f; /* samples in this frame - min. samples */
|
---|
574 | freq = (as_pack[4] >> 3) & 0x07; /* 0 - 48KHz, 1 - 44,1kHz, 2 - 32 kHz */
|
---|
575 | stype = (as_pack[3] & 0x1f); /* 0 - 2CH, 2 - 4CH */
|
---|
576 | quant = as_pack[4] & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */
|
---|
577 |
|
---|
578 | /* note: ach counts PAIRS of channels (i.e. stereo channels) */
|
---|
579 | ach = (stype == 2 || (quant && (freq == 2))) ? 2 : 1;
|
---|
580 |
|
---|
581 | /* Dynamic handling of the audio streams in DV */
|
---|
582 | for (i=0; i<ach; i++) {
|
---|
583 | if (!c->ast[i]) {
|
---|
584 | c->ast[i] = av_new_stream(c->fctx, 0);
|
---|
585 | if (!c->ast[i])
|
---|
586 | break;
|
---|
587 | av_set_pts_info(c->ast[i], 64, 1, 30000);
|
---|
588 | c->ast[i]->codec->codec_type = CODEC_TYPE_AUDIO;
|
---|
589 | c->ast[i]->codec->codec_id = CODEC_ID_PCM_S16LE;
|
---|
590 |
|
---|
591 | av_init_packet(&c->audio_pkt[i]);
|
---|
592 | c->audio_pkt[i].size = 0;
|
---|
593 | c->audio_pkt[i].data = c->audio_buf[i];
|
---|
594 | c->audio_pkt[i].stream_index = c->ast[i]->index;
|
---|
595 | c->audio_pkt[i].flags |= PKT_FLAG_KEY;
|
---|
596 | }
|
---|
597 | c->ast[i]->codec->sample_rate = dv_audio_frequency[freq];
|
---|
598 | c->ast[i]->codec->channels = 2;
|
---|
599 | c->ast[i]->codec->bit_rate = 2 * dv_audio_frequency[freq] * 16;
|
---|
600 | c->ast[i]->start_time = 0;
|
---|
601 | }
|
---|
602 | c->ach = i;
|
---|
603 |
|
---|
604 | return (c->sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */;
|
---|
605 | }
|
---|
606 |
|
---|
607 | static int dv_extract_video_info(DVDemuxContext *c, uint8_t* frame)
|
---|
608 | {
|
---|
609 | const uint8_t* vsc_pack;
|
---|
610 | AVCodecContext* avctx;
|
---|
611 | int apt, is16_9;
|
---|
612 | int size = 0;
|
---|
613 |
|
---|
614 | if (c->sys) {
|
---|
615 | avctx = c->vst->codec;
|
---|
616 |
|
---|
617 | av_set_pts_info(c->vst, 64, c->sys->frame_rate_base, c->sys->frame_rate);
|
---|
618 | avctx->time_base= (AVRational){c->sys->frame_rate_base, c->sys->frame_rate};
|
---|
619 | if(!avctx->width){
|
---|
620 | avctx->width = c->sys->width;
|
---|
621 | avctx->height = c->sys->height;
|
---|
622 | }
|
---|
623 | avctx->pix_fmt = c->sys->pix_fmt;
|
---|
624 |
|
---|
625 | /* finding out SAR is a little bit messy */
|
---|
626 | vsc_pack = dv_extract_pack(frame, dv_video_control);
|
---|
627 | apt = frame[4] & 0x07;
|
---|
628 | is16_9 = (vsc_pack && ((vsc_pack[2] & 0x07) == 0x02 ||
|
---|
629 | (!apt && (vsc_pack[2] & 0x07) == 0x07)));
|
---|
630 | avctx->sample_aspect_ratio = c->sys->sar[is16_9];
|
---|
631 | avctx->bit_rate = av_rescale(c->sys->frame_size * 8,
|
---|
632 | c->sys->frame_rate,
|
---|
633 | c->sys->frame_rate_base);
|
---|
634 | size = c->sys->frame_size;
|
---|
635 | }
|
---|
636 | return size;
|
---|
637 | }
|
---|
638 |
|
---|
639 | /*
|
---|
640 | * The following 6 functions constitute our interface to the world
|
---|
641 | */
|
---|
642 |
|
---|
643 | int dv_assemble_frame(DVMuxContext *c, AVStream* st,
|
---|
644 | const uint8_t* data, int data_size, uint8_t** frame)
|
---|
645 | {
|
---|
646 | uint8_t pcm[8192];
|
---|
647 | int i;
|
---|
648 |
|
---|
649 | *frame = &c->frame_buf[0];
|
---|
650 | if (c->has_audio && c->has_video &&
|
---|
651 | (c->has_audio == -1 || c->has_audio == c->n_ast)) {
|
---|
652 | /* must be a stale frame */
|
---|
653 | dv_format_frame(c, *frame);
|
---|
654 | c->frames++;
|
---|
655 | if (c->has_audio > 0)
|
---|
656 | c->has_audio = 0;
|
---|
657 | c->has_video = 0;
|
---|
658 | }
|
---|
659 |
|
---|
660 | if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
|
---|
661 | /* FIXME: we have to have more sensible approach than this one */
|
---|
662 | if (c->has_video)
|
---|
663 | av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames);
|
---|
664 |
|
---|
665 | dv_inject_video(c, data, *frame);
|
---|
666 | c->has_video = 1;
|
---|
667 | data_size = 0;
|
---|
668 | if (c->has_audio < 0)
|
---|
669 | goto out;
|
---|
670 | }
|
---|
671 |
|
---|
672 | for (i = 0; i < c->n_ast; i++) {
|
---|
673 | int reqasize, fsize;
|
---|
674 | if (st != c->ast[i])
|
---|
675 | continue;
|
---|
676 | reqasize = 4 * dv_audio_frame_size(c->sys, c->frames);
|
---|
677 | fsize = fifo_size(&c->audio_data[i], c->audio_data[i].rptr);
|
---|
678 | if (st->codec->codec_type == CODEC_TYPE_AUDIO ||
|
---|
679 | (c->has_video && fsize >= reqasize)) {
|
---|
680 | if (fsize + data_size >= reqasize && (c->has_audio < c->n_ast)) {
|
---|
681 | if (fsize >= reqasize) {
|
---|
682 | fifo_read(&c->audio_data[i], &pcm[0], reqasize, &c->audio_data[i].rptr);
|
---|
683 | } else {
|
---|
684 | fifo_read(&c->audio_data[i], &pcm[0], fsize, &c->audio_data[i].rptr);
|
---|
685 | memcpy(&pcm[fsize], &data[0], reqasize - fsize);
|
---|
686 | data += reqasize - fsize;
|
---|
687 | data_size -= reqasize - fsize;
|
---|
688 | }
|
---|
689 | dv_inject_audio(c, &pcm[0], i, *frame);
|
---|
690 | c->has_audio += 1;
|
---|
691 | }
|
---|
692 | /* FIXME: we have to have more sensible approach than this one */
|
---|
693 | if (fifo_size(&c->audio_data[i], c->audio_data[i].rptr) + data_size >= 100*AVCODEC_MAX_AUDIO_FRAME_SIZE)
|
---|
694 | av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames);
|
---|
695 | fifo_write(&c->audio_data[i], data, data_size, &c->audio_data[i].wptr);
|
---|
696 | }
|
---|
697 | }
|
---|
698 | out:
|
---|
699 | return ((c->has_audio == -1 || c->has_audio == c->n_ast) && c->has_video) ? c->sys->frame_size : 0;
|
---|
700 | }
|
---|
701 |
|
---|
702 | DVMuxContext* dv_init_mux(AVFormatContext* s)
|
---|
703 | {
|
---|
704 | DVMuxContext *c;
|
---|
705 | AVStream *vst = NULL;
|
---|
706 | int i;
|
---|
707 |
|
---|
708 | /* we support at most 1 video and 2 audio streams */
|
---|
709 | if (s->nb_streams > 3)
|
---|
710 | return NULL;
|
---|
711 |
|
---|
712 | c = av_mallocz(sizeof(DVMuxContext));
|
---|
713 | if (!c)
|
---|
714 | return NULL;
|
---|
715 |
|
---|
716 | c->n_ast = 0;
|
---|
717 | c->ast[0] = c->ast[1] = NULL;
|
---|
718 |
|
---|
719 | /* We have to sort out where audio and where video stream is */
|
---|
720 | for (i=0; i<s->nb_streams; i++) {
|
---|
721 | switch (s->streams[i]->codec->codec_type) {
|
---|
722 | case CODEC_TYPE_VIDEO:
|
---|
723 | vst = s->streams[i];
|
---|
724 | break;
|
---|
725 | case CODEC_TYPE_AUDIO:
|
---|
726 | c->ast[c->n_ast++] = s->streams[i];
|
---|
727 | break;
|
---|
728 | default:
|
---|
729 | goto bail_out;
|
---|
730 | }
|
---|
731 | }
|
---|
732 |
|
---|
733 | /* Some checks -- DV format is very picky about its incoming streams */
|
---|
734 | if (!vst || vst->codec->codec_id != CODEC_ID_DVVIDEO)
|
---|
735 | goto bail_out;
|
---|
736 | for (i=0; i<c->n_ast; i++) {
|
---|
737 | if (c->ast[i] && (c->ast[i]->codec->codec_id != CODEC_ID_PCM_S16LE ||
|
---|
738 | c->ast[i]->codec->sample_rate != 48000 ||
|
---|
739 | c->ast[i]->codec->channels != 2))
|
---|
740 | goto bail_out;
|
---|
741 | }
|
---|
742 | c->sys = dv_codec_profile(vst->codec);
|
---|
743 | if (!c->sys)
|
---|
744 | goto bail_out;
|
---|
745 |
|
---|
746 | if((c->n_ast > 1) && (c->sys->n_difchan < 2)) {
|
---|
747 | /* only 1 stereo pair is allowed in 25Mbps mode */
|
---|
748 | goto bail_out;
|
---|
749 | }
|
---|
750 |
|
---|
751 | /* Ok, everything seems to be in working order */
|
---|
752 | c->frames = 0;
|
---|
753 | c->has_audio = c->n_ast ? 0 : -1;
|
---|
754 | c->has_video = 0;
|
---|
755 | c->start_time = (time_t)s->timestamp;
|
---|
756 | c->aspect = 0; /* 4:3 is the default */
|
---|
757 | if ((int)(av_q2d(vst->codec->sample_aspect_ratio) * vst->codec->width / vst->codec->height * 10) == 17) /* 16:9 */
|
---|
758 | c->aspect = 0x07;
|
---|
759 |
|
---|
760 | for (i=0; i<c->n_ast; i++) {
|
---|
761 | if (c->ast[i] && fifo_init(&c->audio_data[i], 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) < 0) {
|
---|
762 | while (i>0) {
|
---|
763 | i--;
|
---|
764 | fifo_free(&c->audio_data[i]);
|
---|
765 | }
|
---|
766 | goto bail_out;
|
---|
767 | }
|
---|
768 | }
|
---|
769 |
|
---|
770 | dv_format_frame(c, &c->frame_buf[0]);
|
---|
771 |
|
---|
772 | return c;
|
---|
773 |
|
---|
774 | bail_out:
|
---|
775 | av_free(c);
|
---|
776 | return NULL;
|
---|
777 | }
|
---|
778 |
|
---|
779 | void dv_delete_mux(DVMuxContext *c)
|
---|
780 | {
|
---|
781 | int i;
|
---|
782 | for (i=0; i < c->n_ast; i++)
|
---|
783 | fifo_free(&c->audio_data[i]);
|
---|
784 | }
|
---|
785 |
|
---|
786 | DVDemuxContext* dv_init_demux(AVFormatContext *s)
|
---|
787 | {
|
---|
788 | DVDemuxContext *c;
|
---|
789 |
|
---|
790 | c = av_mallocz(sizeof(DVDemuxContext));
|
---|
791 | if (!c)
|
---|
792 | return NULL;
|
---|
793 |
|
---|
794 | c->vst = av_new_stream(s, 0);
|
---|
795 | if (!c->vst) {
|
---|
796 | av_free(c);
|
---|
797 | return NULL;
|
---|
798 | }
|
---|
799 |
|
---|
800 | c->sys = NULL;
|
---|
801 | c->fctx = s;
|
---|
802 | c->ast[0] = c->ast[1] = NULL;
|
---|
803 | c->ach = 0;
|
---|
804 | c->frames = 0;
|
---|
805 | c->abytes = 0;
|
---|
806 |
|
---|
807 | c->vst->codec->codec_type = CODEC_TYPE_VIDEO;
|
---|
808 | c->vst->codec->codec_id = CODEC_ID_DVVIDEO;
|
---|
809 | c->vst->codec->bit_rate = 25000000;
|
---|
810 | c->vst->start_time = 0;
|
---|
811 |
|
---|
812 | return c;
|
---|
813 | }
|
---|
814 |
|
---|
815 | int dv_get_packet(DVDemuxContext *c, AVPacket *pkt)
|
---|
816 | {
|
---|
817 | int size = -1;
|
---|
818 | int i;
|
---|
819 |
|
---|
820 | for (i=0; i<c->ach; i++) {
|
---|
821 | if (c->ast[i] && c->audio_pkt[i].size) {
|
---|
822 | *pkt = c->audio_pkt[i];
|
---|
823 | c->audio_pkt[i].size = 0;
|
---|
824 | size = pkt->size;
|
---|
825 | break;
|
---|
826 | }
|
---|
827 | }
|
---|
828 |
|
---|
829 | return size;
|
---|
830 | }
|
---|
831 |
|
---|
832 | int dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,
|
---|
833 | uint8_t* buf, int buf_size)
|
---|
834 | {
|
---|
835 | int size, i;
|
---|
836 |
|
---|
837 | if (buf_size < DV_PROFILE_BYTES ||
|
---|
838 | !(c->sys = dv_frame_profile(buf)) ||
|
---|
839 | buf_size < c->sys->frame_size) {
|
---|
840 | return -1; /* Broken frame, or not enough data */
|
---|
841 | }
|
---|
842 |
|
---|
843 | /* Queueing audio packet */
|
---|
844 | /* FIXME: in case of no audio/bad audio we have to do something */
|
---|
845 | size = dv_extract_audio_info(c, buf);
|
---|
846 | for (i=0; i<c->ach; i++) {
|
---|
847 | c->audio_pkt[i].size = size;
|
---|
848 | c->audio_pkt[i].pts = c->abytes * 30000*8 / c->ast[i]->codec->bit_rate;
|
---|
849 | }
|
---|
850 | dv_extract_audio(buf, c->audio_buf[0], c->audio_buf[1], c->sys);
|
---|
851 | c->abytes += size;
|
---|
852 |
|
---|
853 | /* Now it's time to return video packet */
|
---|
854 | size = dv_extract_video_info(c, buf);
|
---|
855 | av_init_packet(pkt);
|
---|
856 | pkt->data = buf;
|
---|
857 | pkt->size = size;
|
---|
858 | pkt->flags |= PKT_FLAG_KEY;
|
---|
859 | pkt->stream_index = c->vst->id;
|
---|
860 | pkt->pts = c->frames;
|
---|
861 |
|
---|
862 | c->frames++;
|
---|
863 |
|
---|
864 | return size;
|
---|
865 | }
|
---|
866 |
|
---|
867 | static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c,
|
---|
868 | int64_t timestamp, int flags)
|
---|
869 | {
|
---|
870 | // FIXME: sys may be wrong if last dv_read_packet() failed (buffer is junk)
|
---|
871 | const DVprofile* sys = dv_codec_profile(c->vst->codec);
|
---|
872 | int64_t offset;
|
---|
873 | int64_t size = url_fsize(&s->pb);
|
---|
874 | int64_t max_offset = ((size-1) / sys->frame_size) * sys->frame_size;
|
---|
875 |
|
---|
876 | offset = sys->frame_size * timestamp;
|
---|
877 |
|
---|
878 | if (offset > max_offset) offset = max_offset;
|
---|
879 | else if (offset < 0) offset = 0;
|
---|
880 |
|
---|
881 | return offset;
|
---|
882 | }
|
---|
883 |
|
---|
884 | void dv_flush_audio_packets(DVDemuxContext *c)
|
---|
885 | {
|
---|
886 | c->audio_pkt[0].size = c->audio_pkt[1].size = 0;
|
---|
887 | }
|
---|
888 |
|
---|
889 | /************************************************************
|
---|
890 | * Implementation of the easiest DV storage of all -- raw DV.
|
---|
891 | ************************************************************/
|
---|
892 |
|
---|
893 | typedef struct RawDVContext {
|
---|
894 | DVDemuxContext* dv_demux;
|
---|
895 | uint8_t buf[DV_MAX_FRAME_SIZE];
|
---|
896 | } RawDVContext;
|
---|
897 |
|
---|
898 | static int dv_read_header(AVFormatContext *s,
|
---|
899 | AVFormatParameters *ap)
|
---|
900 | {
|
---|
901 | RawDVContext *c = s->priv_data;
|
---|
902 |
|
---|
903 | c->dv_demux = dv_init_demux(s);
|
---|
904 | if (!c->dv_demux)
|
---|
905 | return -1;
|
---|
906 |
|
---|
907 | if (get_buffer(&s->pb, c->buf, DV_PROFILE_BYTES) <= 0 ||
|
---|
908 | url_fseek(&s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0)
|
---|
909 | return AVERROR_IO;
|
---|
910 |
|
---|
911 | c->dv_demux->sys = dv_frame_profile(c->buf);
|
---|
912 | s->bit_rate = av_rescale(c->dv_demux->sys->frame_size * 8,
|
---|
913 | c->dv_demux->sys->frame_rate,
|
---|
914 | c->dv_demux->sys->frame_rate_base);
|
---|
915 |
|
---|
916 | return 0;
|
---|
917 | }
|
---|
918 |
|
---|
919 |
|
---|
920 | static int dv_read_packet(AVFormatContext *s, AVPacket *pkt)
|
---|
921 | {
|
---|
922 | int size;
|
---|
923 | RawDVContext *c = s->priv_data;
|
---|
924 |
|
---|
925 | size = dv_get_packet(c->dv_demux, pkt);
|
---|
926 |
|
---|
927 | if (size < 0) {
|
---|
928 | size = c->dv_demux->sys->frame_size;
|
---|
929 | if (get_buffer(&s->pb, c->buf, size) <= 0)
|
---|
930 | return AVERROR_IO;
|
---|
931 |
|
---|
932 | size = dv_produce_packet(c->dv_demux, pkt, c->buf, size);
|
---|
933 | }
|
---|
934 |
|
---|
935 | return size;
|
---|
936 | }
|
---|
937 |
|
---|
938 | static int dv_read_seek(AVFormatContext *s, int stream_index,
|
---|
939 | int64_t timestamp, int flags)
|
---|
940 | {
|
---|
941 | RawDVContext *r = s->priv_data;
|
---|
942 | DVDemuxContext *c = r->dv_demux;
|
---|
943 | int64_t offset= dv_frame_offset(s, c, timestamp, flags);
|
---|
944 |
|
---|
945 | c->frames= offset / c->sys->frame_size;
|
---|
946 | if (c->ach)
|
---|
947 | c->abytes= av_rescale(c->frames,
|
---|
948 | c->ast[0]->codec->bit_rate * (int64_t)c->sys->frame_rate_base,
|
---|
949 | 8*c->sys->frame_rate);
|
---|
950 |
|
---|
951 | dv_flush_audio_packets(c);
|
---|
952 | return url_fseek(&s->pb, offset, SEEK_SET);
|
---|
953 | }
|
---|
954 |
|
---|
955 | static int dv_read_close(AVFormatContext *s)
|
---|
956 | {
|
---|
957 | RawDVContext *c = s->priv_data;
|
---|
958 | av_free(c->dv_demux);
|
---|
959 | return 0;
|
---|
960 | }
|
---|
961 |
|
---|
962 | #ifdef CONFIG_MUXERS
|
---|
963 | static int dv_write_header(AVFormatContext *s)
|
---|
964 | {
|
---|
965 | s->priv_data = dv_init_mux(s);
|
---|
966 | if (!s->priv_data) {
|
---|
967 | av_log(s, AV_LOG_ERROR, "Can't initialize DV format!\n"
|
---|
968 | "Make sure that you supply exactly two streams:\n"
|
---|
969 | " video: 25fps or 29.97fps, audio: 2ch/48Khz/PCM\n"
|
---|
970 | " (50Mbps allows an optional second audio stream)\n");
|
---|
971 | return -1;
|
---|
972 | }
|
---|
973 | return 0;
|
---|
974 | }
|
---|
975 |
|
---|
976 | static int dv_write_packet(struct AVFormatContext *s, AVPacket *pkt)
|
---|
977 | {
|
---|
978 | uint8_t* frame;
|
---|
979 | int fsize;
|
---|
980 |
|
---|
981 | fsize = dv_assemble_frame((DVMuxContext *)s->priv_data, s->streams[pkt->stream_index],
|
---|
982 | pkt->data, pkt->size, &frame);
|
---|
983 | if (fsize > 0) {
|
---|
984 | put_buffer(&s->pb, frame, fsize);
|
---|
985 | put_flush_packet(&s->pb);
|
---|
986 | }
|
---|
987 | return 0;
|
---|
988 | }
|
---|
989 |
|
---|
990 | /*
|
---|
991 | * We might end up with some extra A/V data without matching counterpart.
|
---|
992 | * E.g. video data without enough audio to write the complete frame.
|
---|
993 | * Currently we simply drop the last frame. I don't know whether this
|
---|
994 | * is the best strategy of all
|
---|
995 | */
|
---|
996 | static int dv_write_trailer(struct AVFormatContext *s)
|
---|
997 | {
|
---|
998 | dv_delete_mux((DVMuxContext *)s->priv_data);
|
---|
999 | return 0;
|
---|
1000 | }
|
---|
1001 | #endif /* CONFIG_MUXERS */
|
---|
1002 |
|
---|
1003 | static AVInputFormat dv_demuxer = {
|
---|
1004 | "dv",
|
---|
1005 | "DV video format",
|
---|
1006 | sizeof(RawDVContext),
|
---|
1007 | NULL,
|
---|
1008 | dv_read_header,
|
---|
1009 | dv_read_packet,
|
---|
1010 | dv_read_close,
|
---|
1011 | dv_read_seek,
|
---|
1012 | .extensions = "dv,dif",
|
---|
1013 | };
|
---|
1014 |
|
---|
1015 | #ifdef CONFIG_MUXERS
|
---|
1016 | static AVOutputFormat dv_muxer = {
|
---|
1017 | "dv",
|
---|
1018 | "DV video format",
|
---|
1019 | NULL,
|
---|
1020 | "dv",
|
---|
1021 | sizeof(DVMuxContext),
|
---|
1022 | CODEC_ID_PCM_S16LE,
|
---|
1023 | CODEC_ID_DVVIDEO,
|
---|
1024 | dv_write_header,
|
---|
1025 | dv_write_packet,
|
---|
1026 | dv_write_trailer,
|
---|
1027 | };
|
---|
1028 | #endif
|
---|
1029 |
|
---|
1030 | int ff_dv_init(void)
|
---|
1031 | {
|
---|
1032 | av_register_input_format(&dv_demuxer);
|
---|
1033 | #ifdef CONFIG_MUXERS
|
---|
1034 | av_register_output_format(&dv_muxer);
|
---|
1035 | #endif
|
---|
1036 | return 0;
|
---|
1037 | }
|
---|