dvenc.c 16.6 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 * General DV muxer/demuxer
 * Copyright (c) 2003 Roman Shaposhnik
 *
 * Many thanks to Dan Dennedy <dan@dennedy.org> for providing wealth
 * of DV technical info.
 *
 * Raw DV format
9
 * Copyright (c) 2002 Fabrice Bellard
10 11 12 13
 *
 * 50 Mbps (DVCPRO50) support
 * Copyright (c) 2006 Daniel Maas <dmaas@maasdigital.com>
 *
14
 * This file is part of Libav.
15
 *
16
 * Libav is free software; you can redistribute it and/or
17 18
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
19
 * version 2.1 of the License, or (at your option) any later version.
20
 *
21
 * Libav is distributed in the hope that it will be useful,
22 23 24 25 26
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
27
 * License along with Libav; if not, write to the Free Software
28 29 30
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
#include <time.h>
31
#include <stdarg.h>
32

33
#include "avformat.h"
34
#include "internal.h"
35
#include "libavcodec/dv_profile.h"
36
#include "libavcodec/dv.h"
37
#include "dv.h"
38
#include "libavutil/fifo.h"
39
#include "libavutil/mathematics.h"
40

41 42
#define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio

43
struct DVMuxContext {
44
    const AVDVProfile*  sys;           /* current DV profile, e.g.: 525/60, 625/50 */
Diego Biurrun's avatar
Diego Biurrun committed
45 46
    int               n_ast;         /* number of stereo audio streams (up to 2) */
    AVStream         *ast[2];        /* stereo audio streams */
47
    AVFifoBuffer     *audio_data[2]; /* FIFO for storing excessive amounts of PCM */
Diego Biurrun's avatar
Diego Biurrun committed
48
    int               frames;        /* current frame number */
49
    int64_t           start_time;    /* recording start time */
Diego Biurrun's avatar
Diego Biurrun committed
50 51 52
    int               has_audio;     /* frame under construction has audio */
    int               has_video;     /* frame under construction has video */
    uint8_t           frame_buf[DV_MAX_FRAME_SIZE]; /* frame under construction */
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
};

static const int dv_aaux_packs_dist[12][9] = {
    { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
    { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
    { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
    { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
    { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
    { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
    { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
    { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
    { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
    { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
    { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },
    { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },
};

70
static int dv_audio_frame_size(const AVDVProfile* sys, int frame)
71
{
Diego Biurrun's avatar
Diego Biurrun committed
72
    return sys->audio_samples_dist[frame % (sizeof(sys->audio_samples_dist) /
73 74 75
                                            sizeof(sys->audio_samples_dist[0]))];
}

76
static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* buf, ...)
77 78 79 80
{
    struct tm tc;
    time_t ct;
    int ltc_frame;
81
    va_list ap;
82 83 84 85

    buf[0] = (uint8_t)pack_id;
    switch (pack_id) {
    case dv_timecode:
Diego Biurrun's avatar
Diego Biurrun committed
86 87
        ct = (time_t)av_rescale_rnd(c->frames, c->sys->time_base.num,
                                    c->sys->time_base.den, AV_ROUND_DOWN);
88
        ff_brktimegm(ct, &tc);
89 90 91 92
        /*
         * LTC drop-frame frame counter drops two frames (0 and 1) every
         * minute, unless it is exactly divisible by 10
         */
Diego Biurrun's avatar
Diego Biurrun committed
93
        ltc_frame = (c->frames + 2 * ct / 60 - 2 * ct / 600) % c->sys->ltc_divisor;
Diego Biurrun's avatar
Diego Biurrun committed
94 95 96 97 98 99 100 101 102 103 104 105 106 107
        buf[1] = (0                 << 7) | /* color frame: 0 - unsync; 1 - sync mode */
                 (1                 << 6) | /* drop frame timecode: 0 - nondrop; 1 - drop */
                 ((ltc_frame / 10)  << 4) | /* tens of frames */
                 (ltc_frame % 10);          /* units of frames */
        buf[2] = (1                 << 7) | /* biphase mark polarity correction: 0 - even; 1 - odd */
                 ((tc.tm_sec / 10)  << 4) | /* tens of seconds */
                 (tc.tm_sec % 10);          /* units of seconds */
        buf[3] = (1                 << 7) | /* binary group flag BGF0 */
                 ((tc.tm_min / 10)  << 4) | /* tens of minutes */
                 (tc.tm_min % 10);          /* units of minutes */
        buf[4] = (1                 << 7) | /* binary group flag BGF2 */
                 (1                 << 6) | /* binary group flag BGF1 */
                 ((tc.tm_hour / 10) << 4) | /* tens of hours */
                 (tc.tm_hour % 10);         /* units of hours */
108
        break;
109
    case dv_audio_source:  /* AAUX source pack */
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
        va_start(ap, buf);
        buf[1] = (1 << 7) | /* locked mode -- SMPTE only supports locked mode */
                 (1 << 6) | /* reserved -- always 1 */
                 (dv_audio_frame_size(c->sys, c->frames) -
                  c->sys->audio_min_samples[0]);
                            /* # of samples      */
        buf[2] = (0 << 7) | /* multi-stereo      */
                 (0 << 5) | /* #of audio channels per block: 0 -- 1 channel */
                 (0 << 4) | /* pair bit: 0 -- one pair of channels */
                 !!va_arg(ap, int); /* audio mode        */
        buf[3] = (1 << 7) | /* res               */
                 (1 << 6) | /* multi-language flag */
                 (c->sys->dsf << 5) | /*  system: 60fields/50fields */
                 (c->sys->n_difchan & 2); /* definition: 0 -- 25Mbps, 2 -- 50Mbps */
        buf[4] = (1 << 7) | /* emphasis: 1 -- off */
                 (0 << 6) | /* emphasis time constant: 0 -- reserved */
Diego Biurrun's avatar
Diego Biurrun committed
126
                 (0 << 3) | /* frequency: 0 -- 48kHz, 1 -- 44,1kHz, 2 -- 32kHz */
127 128 129
                  0;        /* quantization: 0 -- 16bit linear, 1 -- 12bit nonlinear */
        va_end(ap);
        break;
130
    case dv_audio_control:
131 132 133 134 135 136 137 138 139
        buf[1] = (0 << 6) | /* copy protection: 0 -- unrestricted */
                 (1 << 4) | /* input source: 1 -- digital input */
                 (3 << 2) | /* compression: 3 -- no information */
                  0;        /* misc. info/SMPTE emphasis off */
        buf[2] = (1 << 7) | /* recording start point: 1 -- no */
                 (1 << 6) | /* recording end point: 1 -- no */
                 (1 << 3) | /* recording mode: 1 -- original */
                  7;
        buf[3] = (1 << 7) | /* direction: 1 -- forward */
140
                 (c->sys->pix_fmt == AV_PIX_FMT_YUV420P ? 0x20 : /* speed */
Diego Biurrun's avatar
Diego Biurrun committed
141
                                                       c->sys->ltc_divisor * 4);
142 143 144
        buf[4] = (1 << 7) | /* reserved -- always 1 */
                  0x7f;     /* genre category */
        break;
145 146
    case dv_audio_recdate:
    case dv_video_recdate:  /* VAUX recording date */
147
        ct = c->start_time + av_rescale_rnd(c->frames, c->sys->time_base.num,
Diego Biurrun's avatar
Diego Biurrun committed
148
                                            c->sys->time_base.den, AV_ROUND_DOWN);
149
        ff_brktimegm(ct, &tc);
150 151 152 153 154 155 156 157 158 159 160
        buf[1] = 0xff; /* ds, tm, tens of time zone, units of time zone */
                       /* 0xff is very likely to be "unknown" */
        buf[2] = (3 << 6) | /* reserved -- always 1 */
                 ((tc.tm_mday / 10) << 4) | /* Tens of day */
                 (tc.tm_mday % 10);         /* Units of day */
        buf[3] = /* we set high 4 bits to 0, shouldn't we set them to week? */
                 ((tc.tm_mon / 10) << 4) |    /* Tens of month */
                 (tc.tm_mon  % 10);           /* Units of month */
        buf[4] = (((tc.tm_year % 100) / 10) << 4) | /* Tens of year */
                 (tc.tm_year % 10);                 /* Units of year */
        break;
161 162
    case dv_audio_rectime:  /* AAUX recording time */
    case dv_video_rectime:  /* VAUX recording time */
163 164
        ct = c->start_time + av_rescale_rnd(c->frames, c->sys->time_base.num,
                                                       c->sys->time_base.den, AV_ROUND_DOWN);
165
        ff_brktimegm(ct, &tc);
166 167 168 169 170 171 172 173 174 175 176 177
        buf[1] = (3 << 6) | /* reserved -- always 1 */
                 0x3f; /* tens of frame, units of frame: 0x3f - "unknown" ? */
        buf[2] = (1 << 7) | /* reserved -- always 1 */
                 ((tc.tm_sec / 10) << 4) | /* Tens of seconds */
                 (tc.tm_sec % 10);         /* Units of seconds */
        buf[3] = (1 << 7) | /* reserved -- always 1 */
                 ((tc.tm_min / 10) << 4) | /* Tens of minutes */
                 (tc.tm_min % 10);         /* Units of minutes */
        buf[4] = (3 << 6) | /* reserved -- always 1 */
                 ((tc.tm_hour / 10) << 4) | /* Tens of hours */
                 (tc.tm_hour % 10);         /* Units of hours */
        break;
178
    default:
179
        buf[1] = buf[2] = buf[3] = buf[4] = 0xff;
180 181 182 183 184 185 186 187 188 189
    }
    return 5;
}

static void dv_inject_audio(DVMuxContext *c, int channel, uint8_t* frame_ptr)
{
    int i, j, d, of, size;
    size = 4 * dv_audio_frame_size(c->sys, c->frames);
    frame_ptr += channel * c->sys->difseg_size * 150 * 80;
    for (i = 0; i < c->sys->difseg_size; i++) {
190 191 192 193 194 195 196
        frame_ptr += 6 * 80; /* skip DIF segment header */
        for (j = 0; j < 9; j++) {
            dv_write_pack(dv_aaux_packs_dist[i][j], c, &frame_ptr[3], i >= c->sys->difseg_size/2);
            for (d = 8; d < 80; d+=2) {
                of = c->sys->audio_shuffle[i][j] + (d - 8)/2 * c->sys->audio_stride;
                if (of*2 >= size)
                    continue;
197

198 199
                frame_ptr[d]   = *av_fifo_peek2(c->audio_data[channel], of*2+1); // FIXME: maybe we have to admit
                frame_ptr[d+1] = *av_fifo_peek2(c->audio_data[channel], of*2);   //        that DV is a big-endian PCM
200 201 202
            }
            frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */
        }
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
    }
}

static void dv_inject_metadata(DVMuxContext *c, uint8_t* frame)
{
    int j, k;
    uint8_t* buf;

    for (buf = frame; buf < frame + c->sys->frame_size; buf += 150 * 80) {
        /* DV subcode: 2nd and 3d DIFs */
        for (j = 80; j < 80 * 3; j += 80) {
            for (k = 6; k < 6 * 8; k += 8)
                dv_write_pack(dv_timecode, c, &buf[j+k]);

            if (((long)(buf-frame)/(c->sys->frame_size/(c->sys->difseg_size*c->sys->n_difchan))%c->sys->difseg_size) > 5) { /* FIXME: is this really needed ? */
                dv_write_pack(dv_video_recdate, c, &buf[j+14]);
                dv_write_pack(dv_video_rectime, c, &buf[j+22]);
                dv_write_pack(dv_video_recdate, c, &buf[j+38]);
                dv_write_pack(dv_video_rectime, c, &buf[j+46]);
            }
        }

        /* DV VAUX: 4th, 5th and 6th 3DIFs */
        for (j = 80*3 + 3; j < 80*6; j += 80) {
            dv_write_pack(dv_video_recdate, c, &buf[j+5*2]);
            dv_write_pack(dv_video_rectime, c, &buf[j+5*3]);
            dv_write_pack(dv_video_recdate, c, &buf[j+5*11]);
            dv_write_pack(dv_video_rectime, c, &buf[j+5*12]);
        }
    }
}

/*
 * The following 3 functions constitute our interface to the world
 */

239 240
static int dv_assemble_frame(AVFormatContext *s,
                             DVMuxContext *c, AVStream* st,
241
                             uint8_t* data, int data_size, uint8_t** frame)
242 243 244 245 246 247
{
    int i, reqasize;

    *frame = &c->frame_buf[0];
    reqasize = 4 * dv_audio_frame_size(c->sys, c->frames);

248
    switch (st->codecpar->codec_type) {
249
    case AVMEDIA_TYPE_VIDEO:
250 251
        /* FIXME: we have to have more sensible approach than this one */
        if (c->has_video)
252
            av_log(s, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames);
253
        if (data_size != c->sys->frame_size) {
254
            av_log(s, AV_LOG_ERROR, "Unexpected frame size, %d != %d\n",
255 256 257
                   data_size, c->sys->frame_size);
            return AVERROR(ENOSYS);
        }
258

259 260 261
        memcpy(*frame, data, c->sys->frame_size);
        c->has_video = 1;
        break;
262
    case AVMEDIA_TYPE_AUDIO:
263
        for (i = 0; i < c->n_ast && st != c->ast[i]; i++);
264 265

          /* FIXME: we have to have more sensible approach than this one */
266
        if (av_fifo_size(c->audio_data[i]) + data_size >= 100*MAX_AUDIO_FRAME_SIZE)
267
            av_log(s, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames);
268
        av_fifo_generic_write(c->audio_data[i], data, data_size, NULL);
269

270
        /* Let us see if we've got enough audio for one DV frame. */
271
        c->has_audio |= ((reqasize <= av_fifo_size(c->audio_data[i])) << i);
272

273
        break;
274
    default:
275
        break;
276 277
    }

278
    /* Let us see if we have enough data to construct one DV frame. */
Diego Biurrun's avatar
Diego Biurrun committed
279
    if (c->has_video == 1 && c->has_audio + 1 == 1 << c->n_ast) {
280
        dv_inject_metadata(c, *frame);
281
        c->has_audio = 0;
Diego Biurrun's avatar
Diego Biurrun committed
282
        for (i=0; i < c->n_ast; i++) {
283
            dv_inject_audio(c, i, *frame);
284 285
            av_fifo_drain(c->audio_data[i], reqasize);
            c->has_audio |= ((reqasize <= av_fifo_size(c->audio_data[i])) << i);
286 287 288
        }

        c->has_video = 0;
289

290 291 292 293 294 295 296 297
        c->frames++;

        return c->sys->frame_size;
    }

    return 0;
}

298
static DVMuxContext* dv_init_mux(AVFormatContext* s)
299
{
300
    DVMuxContext *c = s->priv_data;
301
    AVStream *vst = NULL;
302
    AVDictionaryEntry *t;
303 304 305 306 307 308
    int i;

    /* we support at most 1 video and 2 audio streams */
    if (s->nb_streams > 3)
        return NULL;

Diego Biurrun's avatar
Diego Biurrun committed
309
    c->n_ast  = 0;
310 311 312 313
    c->ast[0] = c->ast[1] = NULL;

    /* We have to sort out where audio and where video stream is */
    for (i=0; i<s->nb_streams; i++) {
314
        switch (s->streams[i]->codecpar->codec_type) {
315
        case AVMEDIA_TYPE_VIDEO:
316 317 318
            if (vst) return NULL;
            vst = s->streams[i];
            break;
319
        case AVMEDIA_TYPE_AUDIO:
320 321 322 323 324 325
            if (c->n_ast > 1) return NULL;
            c->ast[c->n_ast++] = s->streams[i];
            break;
        default:
            goto bail_out;
        }
326 327 328
    }

    /* Some checks -- DV format is very picky about its incoming streams */
329
    if (!vst || vst->codecpar->codec_id != AV_CODEC_ID_DVVIDEO)
330 331
        goto bail_out;
    for (i=0; i<c->n_ast; i++) {
332 333 334
        if (c->ast[i] && (c->ast[i]->codecpar->codec_id    != AV_CODEC_ID_PCM_S16LE ||
                          c->ast[i]->codecpar->sample_rate != 48000 ||
                          c->ast[i]->codecpar->channels    != 2))
335 336
            goto bail_out;
    }
337
    c->sys = av_dv_codec_profile(vst->codecpar->width, vst->codecpar->height, vst->codecpar->format);
338 339 340
    if (!c->sys)
        goto bail_out;

Diego Biurrun's avatar
Diego Biurrun committed
341
    if ((c->n_ast > 1) && (c->sys->n_difchan < 2)) {
342 343 344 345 346
        /* only 1 stereo pair is allowed in 25Mbps mode */
        goto bail_out;
    }

    /* Ok, everything seems to be in working order */
Diego Biurrun's avatar
Diego Biurrun committed
347 348 349
    c->frames     = 0;
    c->has_audio  = 0;
    c->has_video  = 0;
350 351
    if (t = av_dict_get(s->metadata, "creation_time", NULL, 0))
        c->start_time = ff_iso8601_to_unix_time(t->value);
352

Diego Biurrun's avatar
Diego Biurrun committed
353
    for (i=0; i < c->n_ast; i++) {
354
        if (c->ast[i] && !(c->audio_data[i]=av_fifo_alloc(100*MAX_AUDIO_FRAME_SIZE))) {
Diego Biurrun's avatar
Diego Biurrun committed
355
            while (i > 0) {
356
                i--;
357
                av_fifo_free(c->audio_data[i]);
358 359 360 361 362 363 364 365 366 367 368
            }
            goto bail_out;
        }
    }

    return c;

bail_out:
    return NULL;
}

369
static void dv_delete_mux(DVMuxContext *c)
370 371 372
{
    int i;
    for (i=0; i < c->n_ast; i++)
373
        av_fifo_free(c->audio_data[i]);
374 375 376 377
}

static int dv_write_header(AVFormatContext *s)
{
378
    if (!dv_init_mux(s)) {
379 380
        av_log(s, AV_LOG_ERROR, "Can't initialize DV format!\n"
                    "Make sure that you supply exactly two streams:\n"
Diego Biurrun's avatar
Diego Biurrun committed
381
                    "     video: 25fps or 29.97fps, audio: 2ch/48kHz/PCM\n"
382 383 384 385 386 387 388 389 390 391 392
                    "     (50Mbps allows an optional second audio stream)\n");
        return -1;
    }
    return 0;
}

static int dv_write_packet(struct AVFormatContext *s, AVPacket *pkt)
{
    uint8_t* frame;
    int fsize;

393
    fsize = dv_assemble_frame(s, s->priv_data, s->streams[pkt->stream_index],
394 395
                              pkt->data, pkt->size, &frame);
    if (fsize > 0) {
396
        avio_write(s->pb, frame, fsize);
397 398 399 400 401 402 403 404 405 406 407 408
    }
    return 0;
}

/*
 * We might end up with some extra A/V data without matching counterpart.
 * E.g. video data without enough audio to write the complete frame.
 * Currently we simply drop the last frame. I don't know whether this
 * is the best strategy of all
 */
static int dv_write_trailer(struct AVFormatContext *s)
{
409
    dv_delete_mux(s->priv_data);
410 411 412
    return 0;
}

413
AVOutputFormat ff_dv_muxer = {
414
    .name              = "dv",
415
    .long_name         = NULL_IF_CONFIG_SMALL("DV (Digital Video)"),
416 417
    .extensions        = "dv",
    .priv_data_size    = sizeof(DVMuxContext),
418 419
    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
    .video_codec       = AV_CODEC_ID_DVVIDEO,
420 421 422
    .write_header      = dv_write_header,
    .write_packet      = dv_write_packet,
    .write_trailer     = dv_write_trailer,
423
};