~ubuntu-branches/debian/sid/mjpegtools/sid

« back to all changes in this revision

Viewing changes to y4mutils/y4mtoqt.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2012-09-02 16:29:46 UTC
  • Revision ID: package-import@ubuntu.com-20120902162946-i1zpl8cjngq9hd6w
Tags: upstream-2.0.0+debian
ImportĀ upstreamĀ versionĀ 2.0.0+debian

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: y4mtoqt.c,v 1.13 2007/05/10 03:07:36 sms00 Exp $
 
3
 *
 
4
 * Utility to place 4:2:2 or 4:4:4 YUV4MPEG2 data in a Quicktime wrapper.   An
 
5
 * audio track can also be added by specifying '-a wavfile' (16bit pcm only).
 
6
 * The interlacing, frame rate, frame size and field order are extracted 
 
7
 * from the YUV4MPEG2 header.  This is the reverse of 'qttoy4m' which dumps
 
8
 * planar data from a Quicktime file (and optionally a specified audio track 
 
9
 * to a wav file).
 
10
 *
 
11
 * Usage: y4mtoqt [-X] [-a wavfile] -o outputfile < 422yuv4mpeg2stream
 
12
 *
 
13
 *   -X enables 10bit packed output, 2vuy becomes v210 and v308 becomes v410.
 
14
*/
 
15
 
 
16
#include "config.h"
 
17
#include <stdio.h>
 
18
#include <stdlib.h>
 
19
#include <quicktime.h>
 
20
#include <lqt.h>
 
21
#include <colormodels.h>
 
22
#include "yuv4mpeg.h"
 
23
#include "avilib.h"
 
24
 
 
25
static  void    usage(void);
 
26
static void do_audio(quicktime_t *, uint8_t *, int, int,  int);
 
27
 
 
28
int
 
29
main(int argc, char **argv)
 
30
        {
 
31
        char    *outfilename = NULL;
 
32
        char    *audiofilename = NULL;
 
33
        uint8_t *yuv[3], *p;
 
34
        uint16_t *p16;
 
35
        uint16_t *yuv10[3];
 
36
        int     fdin, y_len, u_len, v_len, nfields = 1, dominance = 0, afd = -1;
 
37
        int     imodel = 0, allow_wrong_yv12 = 0;
 
38
        int     err, i, c, frames, channels = 0, y4mchroma, tenbit = 0;
 
39
        char    *qtchroma = NULL;
 
40
        quicktime_t *qtf;
 
41
        quicktime_pasp_t pasp;
 
42
#if 0
 
43
        quicktime_colr_t colr;
 
44
#endif
 
45
        quicktime_clap_t clap;
 
46
        y4m_stream_info_t istream;
 
47
        y4m_frame_info_t iframe;
 
48
        y4m_ratio_t rate, sar;
 
49
        struct wave_header wavhdr;
 
50
        y4m_accept_extensions(1);
 
51
        
 
52
        fdin = fileno(stdin);
 
53
 
 
54
        opterr = 0;
 
55
        while   ((c = getopt(argc, argv, "ko:a:X")) != -1)
 
56
                {
 
57
                switch  (c)
 
58
                        {
 
59
                        case    'k':
 
60
                                allow_wrong_yv12 = 1;
 
61
                                break;
 
62
                        case    'X':
 
63
                                tenbit = 1;
 
64
                                break;
 
65
                        case    'o':
 
66
                                outfilename = optarg;
 
67
                                break;
 
68
                        case    'a':
 
69
                                audiofilename = optarg;
 
70
                                break;
 
71
                        case    '?':
 
72
                        default:
 
73
                                usage();
 
74
                        }
 
75
                }
 
76
        argc -= optind;
 
77
        argv += optind;
 
78
        if      (argc)
 
79
                usage();
 
80
 
 
81
        if      (!outfilename)
 
82
                usage();
 
83
 
 
84
        if      (audiofilename)
 
85
                {
 
86
                afd = open(audiofilename, O_RDONLY);
 
87
                if      (afd < 0)
 
88
                        mjpeg_error_exit1("Can not open audio file '%s'", 
 
89
                                                audiofilename);
 
90
                if      (AVI_read_wave_header(afd, &wavhdr) == -1)
 
91
                        mjpeg_error_exit1("'%s' is not a valid WAV file",
 
92
                                                audiofilename);
 
93
                channels = wavhdr.common.wChannels;
 
94
                }
 
95
 
 
96
        y4m_init_stream_info(&istream);
 
97
        y4m_init_frame_info(&iframe);
 
98
 
 
99
        err = y4m_read_stream_header(fdin, &istream);
 
100
        if      (err != Y4M_OK)
 
101
                mjpeg_error_exit1("Input header error: %s", y4m_strerr(err));
 
102
 
 
103
        if      (y4m_si_get_plane_count(&istream) != 3)
 
104
                mjpeg_error_exit1("Only 3 plane formats supported");
 
105
 
 
106
        rate = y4m_si_get_framerate(&istream);
 
107
 
 
108
        switch  (y4mchroma = y4m_si_get_chroma(&istream))
 
109
                {
 
110
                case    Y4M_CHROMA_420MPEG2:
 
111
                case    Y4M_CHROMA_420JPEG:
 
112
                        /*
 
113
                         * Quicktime doesn't appear to have a way to reliably
 
114
                         * tell the two non-PALDV variants apart so treat them
 
115
                         * both the same (like most other software in the world)
 
116
                        */
 
117
                        qtchroma = QUICKTIME_YUV420;    /* yv12 */
 
118
                        imodel = BC_YUV420P;
 
119
                        break;
 
120
                case    Y4M_CHROMA_422:
 
121
                        if      (tenbit)
 
122
                                qtchroma = QUICKTIME_V210;
 
123
                        else
 
124
                                {
 
125
                                qtchroma = QUICKTIME_2VUY;
 
126
                                imodel = BC_YUV422P;    /* Input is planar */
 
127
                                }
 
128
                        break;
 
129
                case    Y4M_CHROMA_444:
 
130
                        if      (tenbit)
 
131
                                qtchroma = QUICKTIME_V410;
 
132
                        else
 
133
                                {
 
134
                                qtchroma = QUICKTIME_V308;
 
135
                                imodel = BC_YUV444P;  /* Need this?? */
 
136
                                }
 
137
                        break;
 
138
                default:
 
139
                        mjpeg_error_exit1("unsupported chroma sampling: %s",
 
140
                                y4m_chroma_keyword(y4mchroma));
 
141
                        break;
 
142
                }
 
143
 
 
144
        y_len = y4m_si_get_plane_length(&istream, 0);
 
145
        u_len = y4m_si_get_plane_length(&istream, 1);
 
146
        v_len = y4m_si_get_plane_length(&istream, 2);
 
147
        yuv[0] = malloc(y_len);
 
148
        yuv[1] = malloc(u_len);
 
149
        yuv[2] = malloc(v_len);
 
150
        if      (tenbit)
 
151
                {
 
152
                yuv10[0] = malloc(y_len * sizeof(uint16_t));
 
153
                yuv10[1] = malloc(u_len * sizeof(uint16_t));
 
154
                yuv10[2] = malloc(v_len * sizeof(uint16_t));
 
155
                }
 
156
 
 
157
        qtf = quicktime_open(outfilename, 0, 1);
 
158
        if      (!qtf)
 
159
                mjpeg_error_exit1("quicktime_open(%s,0,1) failed", outfilename);
 
160
 
 
161
        quicktime_set_video(qtf, 1,
 
162
                                y4m_si_get_width(&istream),
 
163
                                y4m_si_get_height(&istream),
 
164
                                (double) rate.n / rate.d,
 
165
                                qtchroma);
 
166
 
 
167
        if      (imodel != 0)
 
168
                lqt_set_cmodel(qtf, 0, imodel);
 
169
 
 
170
        if      (audiofilename)
 
171
                quicktime_set_audio(qtf, channels,
 
172
                                        wavhdr.common.dwSamplesPerSec,
 
173
                                        wavhdr.common.wBitsPerSample,
 
174
                                        QUICKTIME_TWOS);
 
175
/*
 
176
 * http://developer.apple.com/quicktime/icefloe/dispatch019.html#fiel
 
177
 *
 
178
 * "dominance" is what Apple calls "detail".  From what I can figure out
 
179
 * the "bottom field" first corresponds to a "detail" setting of 14 and
 
180
 * "top field first" is a "detail" setting of 9.
 
181
*/
 
182
        switch  (y4m_si_get_interlace(&istream))
 
183
                {
 
184
                case    Y4M_ILACE_BOTTOM_FIRST:
 
185
                        dominance = 14; /* Weird but that's what Apple says */
 
186
                        nfields = 2;
 
187
                        break;
 
188
                case    Y4M_ILACE_TOP_FIRST:
 
189
                        dominance = 9;
 
190
                        nfields = 2;
 
191
                        break;
 
192
                case    Y4M_UNKNOWN:
 
193
                case    Y4M_ILACE_NONE:
 
194
                        dominance = 0;
 
195
                        nfields = 1;
 
196
                        break;
 
197
                case    Y4M_ILACE_MIXED:
 
198
                        mjpeg_error_exit1("Mixed field dominance unsupported");
 
199
                        break;
 
200
                default:
 
201
                        mjpeg_error_exit1("UNKNOWN field dominance %d",
 
202
                                y4m_si_get_interlace(&istream));
 
203
                        break;
 
204
                }
 
205
 
 
206
        if      (lqt_set_fiel(qtf, 0, nfields, dominance) == 0)
 
207
                mjpeg_error_exit1("lqt_set_fiel(qtf, 0, %d, %d) failed",
 
208
                                nfields, dominance);
 
209
 
 
210
        sar = y4m_si_get_sampleaspect(&istream);
 
211
        if      (Y4M_RATIO_EQL(sar, y4m_sar_UNKNOWN))
 
212
                pasp.hSpacing = pasp.vSpacing = 1;
 
213
        else
 
214
                {
 
215
                pasp.hSpacing = sar.n;
 
216
                pasp.vSpacing = sar.d;
 
217
                }
 
218
        if      (lqt_set_pasp(qtf, 0, &pasp) == 0)
 
219
                mjpeg_error_exit1("lqt_set_pasp(qtf, 0, %d/%d) failed",
 
220
                        pasp.hSpacing, pasp.vSpacing);
 
221
 
 
222
/*
 
223
 * Don't do this for now - it can crash FinalCutPro if the colr atom is
 
224
 * not exactly correct.
 
225
*/
 
226
#if     0
 
227
        colr.colorParamType = 'nclc';
 
228
        colr.primaries = 2;
 
229
        colr.transferFunction = 2;
 
230
        colr.matrix = 2;
 
231
        if      (lqt_set_colr(qtf, 0, &colr) == 0)
 
232
                mjpeg_error_exit1("lqt_set_colr(qtf, 0,...) failed");
 
233
#endif
 
234
        clap.cleanApertureWidthN = y4m_si_get_width (&istream);;
 
235
        clap.cleanApertureWidthD = 1;
 
236
        clap.cleanApertureHeightN = y4m_si_get_height (&istream);
 
237
        clap.cleanApertureHeightD = 1;
 
238
        clap.horizOffN = 0;
 
239
        clap.horizOffD = 1;
 
240
        clap.vertOffN = 0;
 
241
        clap.vertOffD = 1;
 
242
        if      (lqt_set_clap(qtf, 0, &clap) == 0)
 
243
                mjpeg_error_exit1("lqt_set_clap(qtf, 0, ...) failed");
 
244
 
 
245
        for     (;y4m_read_frame(fdin,&istream,&iframe,yuv) == Y4M_OK; frames++)
 
246
                {
 
247
                if      (tenbit)
 
248
                        {
 
249
                        p = yuv[0];
 
250
                        p16 = yuv10[0];
 
251
                        for     (i = 0; i < y_len; i++)
 
252
                                *p16++ = *p++ << 8;
 
253
                        p = yuv[1];
 
254
                        p16 = yuv10[1];
 
255
                        for     (i = 0; i < u_len; i++)
 
256
                                *p16++ = *p++ << 8;
 
257
                        p = yuv[2];
 
258
                        p16 = yuv10[2];
 
259
                        for     (i = 0; i < v_len; i++)
 
260
                                *p16++ = *p++ << 8;
 
261
                        }
 
262
/*
 
263
 * What libquicktime calls 'yv12' (QUICKTIME_YUV420) is actually 'iyuv' 
 
264
 * (also known as 'i420').  In order to make the data match the fourcc/label
 
265
 * the U and V planes need to be swapped.  After all, if the file is labeled 
 
266
 * 'yv12' then the data should be in 'yv12' order!
 
267
 *
 
268
 * Breakage, for compatiblity with quicktime4linux, can be forced by using
 
269
 * '-k'.  This allows storing 'iyuv' ('i420') data inside a file that is 
 
270
 * labeled as 'yv12' :(
 
271
 *
 
272
 * It should be noted that very very little outside of V4L knows anything
 
273
 * about uncompressed 4:2:0 - the 4:2:0 color space is used but only with
 
274
 * compressed formats it seems.
 
275
*/
 
276
 
 
277
                if      (strcmp(qtchroma, QUICKTIME_YUV420) == 0)
 
278
                        {
 
279
                        if      (allow_wrong_yv12 == 0)
 
280
                                {
 
281
                                p = yuv[1];
 
282
                                yuv[1] = yuv[2];
 
283
                                yuv[2] = p;
 
284
                                }
 
285
                        }
 
286
 
 
287
                err = quicktime_encode_video(qtf, tenbit ? (uint8_t **)yuv10: yuv, 0);
 
288
                if      (err != 0)
 
289
                        mjpeg_error_exit1("quicktime_encode_video failed.");
 
290
                }
 
291
 
 
292
        if      (audiofilename)
 
293
                {
 
294
                uint8_t *buffer;
 
295
                int bufsize, n, bps;
 
296
 
 
297
                mjpeg_info("channels %d SamplesPerSec %d bits_sample %d",
 
298
                        channels, wavhdr.common.dwSamplesPerSec,
 
299
                                  wavhdr.common.wBitsPerSample);
 
300
 
 
301
                bps = (wavhdr.common.wBitsPerSample + 7)/8;
 
302
                bufsize = 8192 * channels * bps;
 
303
                buffer = malloc(bufsize);
 
304
                while   ((n = AVI_read_wave_pcm_data(afd, buffer, bufsize)) > 0)
 
305
                        do_audio(qtf, buffer, channels, bps, n / (channels * bps));
 
306
                }
 
307
        quicktime_close(qtf);
 
308
        exit(0);
 
309
        }
 
310
 
 
311
static void 
 
312
do_audio(quicktime_t *qtf, uint8_t *buff, int channels, int bps, int samps)
 
313
        {
 
314
        int     res;
 
315
        int     i, j;
 
316
        int16_t *qt_audio = (int16_t *)buff, **qt_audion;
 
317
 
 
318
        qt_audion = malloc(channels * sizeof (int16_t **));
 
319
        for     (i = 0; i < channels; i++)
 
320
                qt_audion[i] = (int16_t *)malloc(samps * bps);
 
321
 
 
322
        /* Deinterleave the audio into separate channel buffers */
 
323
        for     (i = 0; i < samps; i++)
 
324
                {
 
325
                for     (j = 0; j < channels; j++)
 
326
                        qt_audion[j][i] = qt_audio[(channels*i) + j];
 
327
                }
 
328
        res = lqt_encode_audio_track(qtf, qt_audion, NULL, samps, 0);
 
329
        for     (j = 0; j < channels; j++)
 
330
                free(qt_audion[j]);
 
331
        free(qt_audion);
 
332
        }
 
333
 
 
334
static void
 
335
usage()
 
336
        {
 
337
        mjpeg_warn("usage: [-k] [-X] [-a inputwavfile] -o outfile");
 
338
        mjpeg_warn("       -X = use v210 (default 2vuy) for 4:2:2, v410 (default v308) for 4:4:4");
 
339
        mjpeg_warn("       -k = do not perform lqt workaround (U and V plane swap) (default 0 - i.e. DO the workaround)");
 
340
        exit(1);
 
341
        }