xref: /third_party/ffmpeg/libavformat/dv.c (revision cabdff1a)
1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * General DV demuxer
3cabdff1aSopenharmony_ci * Copyright (c) 2003 Roman Shaposhnik
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * Many thanks to Dan Dennedy <dan@dennedy.org> for providing wealth
6cabdff1aSopenharmony_ci * of DV technical info.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * Raw DV format
9cabdff1aSopenharmony_ci * Copyright (c) 2002 Fabrice Bellard
10cabdff1aSopenharmony_ci *
11cabdff1aSopenharmony_ci * 50 Mbps (DVCPRO50) and 100 Mbps (DVCPRO HD) support
12cabdff1aSopenharmony_ci * Copyright (c) 2006 Daniel Maas <dmaas@maasdigital.com>
13cabdff1aSopenharmony_ci * Funded by BBC Research & Development
14cabdff1aSopenharmony_ci *
15cabdff1aSopenharmony_ci * This file is part of FFmpeg.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
18cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
20cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
21cabdff1aSopenharmony_ci *
22cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
23cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
24cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25cabdff1aSopenharmony_ci * Lesser General Public License for more details.
26cabdff1aSopenharmony_ci *
27cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
28cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
29cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30cabdff1aSopenharmony_ci */
31cabdff1aSopenharmony_ci#include <time.h>
32cabdff1aSopenharmony_ci#include "avformat.h"
33cabdff1aSopenharmony_ci#include "internal.h"
34cabdff1aSopenharmony_ci#include "libavcodec/dv_profile.h"
35cabdff1aSopenharmony_ci#include "libavcodec/dv.h"
36cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h"
37cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h"
38cabdff1aSopenharmony_ci#include "libavutil/mathematics.h"
39cabdff1aSopenharmony_ci#include "libavutil/timecode.h"
40cabdff1aSopenharmony_ci#include "dv.h"
41cabdff1aSopenharmony_ci#include "libavutil/avassert.h"
42cabdff1aSopenharmony_ci
43cabdff1aSopenharmony_ci// Must be kept in sync with AVPacket
44cabdff1aSopenharmony_cistruct DVPacket {
45cabdff1aSopenharmony_ci    int64_t  pts;
46cabdff1aSopenharmony_ci    uint8_t *data;
47cabdff1aSopenharmony_ci    int      size;
48cabdff1aSopenharmony_ci    int      stream_index;
49cabdff1aSopenharmony_ci    int      flags;
50cabdff1aSopenharmony_ci    int64_t  pos;
51cabdff1aSopenharmony_ci    int64_t  duration;
52cabdff1aSopenharmony_ci};
53cabdff1aSopenharmony_ci
54cabdff1aSopenharmony_cistruct DVDemuxContext {
55cabdff1aSopenharmony_ci    const AVDVProfile*  sys;    /* Current DV profile. E.g.: 525/60, 625/50 */
56cabdff1aSopenharmony_ci    AVFormatContext*  fctx;
57cabdff1aSopenharmony_ci    AVStream*         vst;
58cabdff1aSopenharmony_ci    AVStream*         ast[4];
59cabdff1aSopenharmony_ci    struct DVPacket   audio_pkt[4];
60cabdff1aSopenharmony_ci    uint8_t           audio_buf[4][8192];
61cabdff1aSopenharmony_ci    int               ach;
62cabdff1aSopenharmony_ci    int               frames;
63cabdff1aSopenharmony_ci};
64cabdff1aSopenharmony_ci
65cabdff1aSopenharmony_cistatic inline uint16_t dv_audio_12to16(uint16_t sample)
66cabdff1aSopenharmony_ci{
67cabdff1aSopenharmony_ci    uint16_t shift, result;
68cabdff1aSopenharmony_ci
69cabdff1aSopenharmony_ci    sample = (sample < 0x800) ? sample : sample | 0xf000;
70cabdff1aSopenharmony_ci    shift  = (sample & 0xf00) >> 8;
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_ci    if (shift < 0x2 || shift > 0xd) {
73cabdff1aSopenharmony_ci        result = sample;
74cabdff1aSopenharmony_ci    } else if (shift < 0x8) {
75cabdff1aSopenharmony_ci        shift--;
76cabdff1aSopenharmony_ci        result = (sample - (256 * shift)) << shift;
77cabdff1aSopenharmony_ci    } else {
78cabdff1aSopenharmony_ci        shift  = 0xe - shift;
79cabdff1aSopenharmony_ci        result = ((sample + ((256 * shift) + 1)) << shift) - 1;
80cabdff1aSopenharmony_ci    }
81cabdff1aSopenharmony_ci
82cabdff1aSopenharmony_ci    return result;
83cabdff1aSopenharmony_ci}
84cabdff1aSopenharmony_ci
85cabdff1aSopenharmony_cistatic const uint8_t *dv_extract_pack(const uint8_t *frame, enum dv_pack_type t)
86cabdff1aSopenharmony_ci{
87cabdff1aSopenharmony_ci    int offs;
88cabdff1aSopenharmony_ci    int c;
89cabdff1aSopenharmony_ci
90cabdff1aSopenharmony_ci    for (c = 0; c < 10; c++) {
91cabdff1aSopenharmony_ci        switch (t) {
92cabdff1aSopenharmony_ci        case dv_audio_source:
93cabdff1aSopenharmony_ci            if (c&1)    offs = (80 * 6 + 80 * 16 * 0 + 3 + c*12000);
94cabdff1aSopenharmony_ci            else        offs = (80 * 6 + 80 * 16 * 3 + 3 + c*12000);
95cabdff1aSopenharmony_ci            break;
96cabdff1aSopenharmony_ci        case dv_audio_control:
97cabdff1aSopenharmony_ci            if (c&1)    offs = (80 * 6 + 80 * 16 * 1 + 3 + c*12000);
98cabdff1aSopenharmony_ci            else        offs = (80 * 6 + 80 * 16 * 4 + 3 + c*12000);
99cabdff1aSopenharmony_ci            break;
100cabdff1aSopenharmony_ci        case dv_video_control:
101cabdff1aSopenharmony_ci            if (c&1)    offs = (80 * 3 + 8      + c*12000);
102cabdff1aSopenharmony_ci            else        offs = (80 * 5 + 48 + 5 + c*12000);
103cabdff1aSopenharmony_ci            break;
104cabdff1aSopenharmony_ci        case dv_timecode:
105cabdff1aSopenharmony_ci            offs = (80*1 + 3 + 3);
106cabdff1aSopenharmony_ci            break;
107cabdff1aSopenharmony_ci        default:
108cabdff1aSopenharmony_ci            return NULL;
109cabdff1aSopenharmony_ci        }
110cabdff1aSopenharmony_ci        if (frame[offs] == t)
111cabdff1aSopenharmony_ci            break;
112cabdff1aSopenharmony_ci    }
113cabdff1aSopenharmony_ci
114cabdff1aSopenharmony_ci    return frame[offs] == t ? &frame[offs] : NULL;
115cabdff1aSopenharmony_ci}
116cabdff1aSopenharmony_ci
117cabdff1aSopenharmony_cistatic const int dv_audio_frequency[3] = {
118cabdff1aSopenharmony_ci    48000, 44100, 32000,
119cabdff1aSopenharmony_ci};
120cabdff1aSopenharmony_ci
121cabdff1aSopenharmony_ci/*
122cabdff1aSopenharmony_ci * There's a couple of assumptions being made here:
123cabdff1aSopenharmony_ci * 1. By default we silence erroneous (0x8000/16-bit 0x800/12-bit) audio samples.
124cabdff1aSopenharmony_ci *    We can pass them upwards when libavcodec will be ready to deal with them.
125cabdff1aSopenharmony_ci * 2. We don't do software emphasis.
126cabdff1aSopenharmony_ci * 3. Audio is always returned as 16-bit linear samples: 12-bit nonlinear samples
127cabdff1aSopenharmony_ci *    are converted into 16-bit linear ones.
128cabdff1aSopenharmony_ci */
129cabdff1aSopenharmony_cistatic int dv_extract_audio(const uint8_t *frame, uint8_t **ppcm,
130cabdff1aSopenharmony_ci                            const AVDVProfile *sys)
131cabdff1aSopenharmony_ci{
132cabdff1aSopenharmony_ci    int size, chan, i, j, d, of, smpls, freq, quant, half_ch;
133cabdff1aSopenharmony_ci    uint16_t lc, rc;
134cabdff1aSopenharmony_ci    const uint8_t *as_pack;
135cabdff1aSopenharmony_ci    uint8_t *pcm, ipcm;
136cabdff1aSopenharmony_ci
137cabdff1aSopenharmony_ci    as_pack = dv_extract_pack(frame, dv_audio_source);
138cabdff1aSopenharmony_ci    if (!as_pack)    /* No audio ? */
139cabdff1aSopenharmony_ci        return 0;
140cabdff1aSopenharmony_ci
141cabdff1aSopenharmony_ci    smpls = as_pack[1]      & 0x3f; /* samples in this frame - min. samples */
142cabdff1aSopenharmony_ci    freq  = as_pack[4] >> 3 & 0x07; /* 0 - 48kHz, 1 - 44,1kHz, 2 - 32kHz */
143cabdff1aSopenharmony_ci    quant = as_pack[4]      & 0x07; /* 0 - 16-bit linear, 1 - 12-bit nonlinear */
144cabdff1aSopenharmony_ci
145cabdff1aSopenharmony_ci    if (quant > 1)
146cabdff1aSopenharmony_ci        return -1;  /* unsupported quantization */
147cabdff1aSopenharmony_ci
148cabdff1aSopenharmony_ci    if (freq >= FF_ARRAY_ELEMS(dv_audio_frequency))
149cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
150cabdff1aSopenharmony_ci
151cabdff1aSopenharmony_ci    size    = (sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */
152cabdff1aSopenharmony_ci    half_ch = sys->difseg_size / 2;
153cabdff1aSopenharmony_ci
154cabdff1aSopenharmony_ci    /* We work with 720p frames split in half, thus even frames have
155cabdff1aSopenharmony_ci     * channels 0,1 and odd 2,3. */
156cabdff1aSopenharmony_ci    ipcm = (sys->height == 720 && !(frame[1] & 0x0C)) ? 2 : 0;
157cabdff1aSopenharmony_ci
158cabdff1aSopenharmony_ci    if (ipcm + sys->n_difchan > (quant == 1 ? 2 : 4)) {
159cabdff1aSopenharmony_ci        av_log(NULL, AV_LOG_ERROR, "too many dv pcm frames\n");
160cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
161cabdff1aSopenharmony_ci    }
162cabdff1aSopenharmony_ci
163cabdff1aSopenharmony_ci    /* for each DIF channel */
164cabdff1aSopenharmony_ci    for (chan = 0; chan < sys->n_difchan; chan++) {
165cabdff1aSopenharmony_ci        av_assert0(ipcm<4);
166cabdff1aSopenharmony_ci        pcm = ppcm[ipcm++];
167cabdff1aSopenharmony_ci        if (!pcm)
168cabdff1aSopenharmony_ci            break;
169cabdff1aSopenharmony_ci
170cabdff1aSopenharmony_ci        /* for each DIF segment */
171cabdff1aSopenharmony_ci        for (i = 0; i < sys->difseg_size; i++) {
172cabdff1aSopenharmony_ci            frame += 6 * 80; /* skip DIF segment header */
173cabdff1aSopenharmony_ci            if (quant == 1 && i == half_ch) {
174cabdff1aSopenharmony_ci                /* next stereo channel (12-bit mode only) */
175cabdff1aSopenharmony_ci                av_assert0(ipcm<4);
176cabdff1aSopenharmony_ci                pcm = ppcm[ipcm++];
177cabdff1aSopenharmony_ci                if (!pcm)
178cabdff1aSopenharmony_ci                    break;
179cabdff1aSopenharmony_ci            }
180cabdff1aSopenharmony_ci
181cabdff1aSopenharmony_ci            /* for each AV sequence */
182cabdff1aSopenharmony_ci            for (j = 0; j < 9; j++) {
183cabdff1aSopenharmony_ci                for (d = 8; d < 80; d += 2) {
184cabdff1aSopenharmony_ci                    if (quant == 0) {  /* 16-bit quantization */
185cabdff1aSopenharmony_ci                        of = sys->audio_shuffle[i][j] +
186cabdff1aSopenharmony_ci                             (d - 8) / 2 * sys->audio_stride;
187cabdff1aSopenharmony_ci                        if (of * 2 >= size)
188cabdff1aSopenharmony_ci                            continue;
189cabdff1aSopenharmony_ci
190cabdff1aSopenharmony_ci                        /* FIXME: maybe we have to admit that DV is a
191cabdff1aSopenharmony_ci                         * big-endian PCM */
192cabdff1aSopenharmony_ci                        pcm[of * 2]     = frame[d + 1];
193cabdff1aSopenharmony_ci                        pcm[of * 2 + 1] = frame[d];
194cabdff1aSopenharmony_ci
195cabdff1aSopenharmony_ci                        if (pcm[of * 2 + 1] == 0x80 && pcm[of * 2] == 0x00)
196cabdff1aSopenharmony_ci                            pcm[of * 2 + 1] = 0;
197cabdff1aSopenharmony_ci                    } else {           /* 12-bit quantization */
198cabdff1aSopenharmony_ci                        lc = ((uint16_t)frame[d]     << 4) |
199cabdff1aSopenharmony_ci                             ((uint16_t)frame[d + 2] >> 4);
200cabdff1aSopenharmony_ci                        rc = ((uint16_t)frame[d + 1] << 4) |
201cabdff1aSopenharmony_ci                             ((uint16_t)frame[d + 2] & 0x0f);
202cabdff1aSopenharmony_ci                        lc = (lc == 0x800 ? 0 : dv_audio_12to16(lc));
203cabdff1aSopenharmony_ci                        rc = (rc == 0x800 ? 0 : dv_audio_12to16(rc));
204cabdff1aSopenharmony_ci
205cabdff1aSopenharmony_ci                        of = sys->audio_shuffle[i % half_ch][j] +
206cabdff1aSopenharmony_ci                             (d - 8) / 3 * sys->audio_stride;
207cabdff1aSopenharmony_ci                        if (of * 2 >= size)
208cabdff1aSopenharmony_ci                            continue;
209cabdff1aSopenharmony_ci
210cabdff1aSopenharmony_ci                        /* FIXME: maybe we have to admit that DV is a
211cabdff1aSopenharmony_ci                         * big-endian PCM */
212cabdff1aSopenharmony_ci                        pcm[of * 2]     = lc & 0xff;
213cabdff1aSopenharmony_ci                        pcm[of * 2 + 1] = lc >> 8;
214cabdff1aSopenharmony_ci                        of = sys->audio_shuffle[i % half_ch + half_ch][j] +
215cabdff1aSopenharmony_ci                             (d - 8) / 3 * sys->audio_stride;
216cabdff1aSopenharmony_ci                        /* FIXME: maybe we have to admit that DV is a
217cabdff1aSopenharmony_ci                         * big-endian PCM */
218cabdff1aSopenharmony_ci                        pcm[of * 2]     = rc & 0xff;
219cabdff1aSopenharmony_ci                        pcm[of * 2 + 1] = rc >> 8;
220cabdff1aSopenharmony_ci                        ++d;
221cabdff1aSopenharmony_ci                    }
222cabdff1aSopenharmony_ci                }
223cabdff1aSopenharmony_ci
224cabdff1aSopenharmony_ci                frame += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */
225cabdff1aSopenharmony_ci            }
226cabdff1aSopenharmony_ci        }
227cabdff1aSopenharmony_ci    }
228cabdff1aSopenharmony_ci
229cabdff1aSopenharmony_ci    return size;
230cabdff1aSopenharmony_ci}
231cabdff1aSopenharmony_ci
232cabdff1aSopenharmony_cistatic int dv_extract_audio_info(DVDemuxContext *c, const uint8_t *frame)
233cabdff1aSopenharmony_ci{
234cabdff1aSopenharmony_ci    const uint8_t *as_pack;
235cabdff1aSopenharmony_ci    int freq, stype, smpls, quant, i, ach;
236cabdff1aSopenharmony_ci
237cabdff1aSopenharmony_ci    as_pack = dv_extract_pack(frame, dv_audio_source);
238cabdff1aSopenharmony_ci    if (!as_pack || !c->sys) {    /* No audio ? */
239cabdff1aSopenharmony_ci        c->ach = 0;
240cabdff1aSopenharmony_ci        return 0;
241cabdff1aSopenharmony_ci    }
242cabdff1aSopenharmony_ci
243cabdff1aSopenharmony_ci    smpls = as_pack[1]      & 0x3f; /* samples in this frame - min. samples */
244cabdff1aSopenharmony_ci    freq  = as_pack[4] >> 3 & 0x07; /* 0 - 48kHz, 1 - 44,1kHz, 2 - 32kHz */
245cabdff1aSopenharmony_ci    stype = as_pack[3]      & 0x1f; /* 0 - 2CH, 2 - 4CH, 3 - 8CH */
246cabdff1aSopenharmony_ci    quant = as_pack[4]      & 0x07; /* 0 - 16-bit linear, 1 - 12-bit nonlinear */
247cabdff1aSopenharmony_ci
248cabdff1aSopenharmony_ci    if (freq >= FF_ARRAY_ELEMS(dv_audio_frequency)) {
249cabdff1aSopenharmony_ci        av_log(c->fctx, AV_LOG_ERROR,
250cabdff1aSopenharmony_ci               "Unrecognized audio sample rate index (%d)\n", freq);
251cabdff1aSopenharmony_ci        return 0;
252cabdff1aSopenharmony_ci    }
253cabdff1aSopenharmony_ci
254cabdff1aSopenharmony_ci    if (stype > 3) {
255cabdff1aSopenharmony_ci        av_log(c->fctx, AV_LOG_ERROR, "stype %d is invalid\n", stype);
256cabdff1aSopenharmony_ci        c->ach = 0;
257cabdff1aSopenharmony_ci        return 0;
258cabdff1aSopenharmony_ci    }
259cabdff1aSopenharmony_ci
260cabdff1aSopenharmony_ci    /* note: ach counts PAIRS of channels (i.e. stereo channels) */
261cabdff1aSopenharmony_ci    ach = ((int[4]) { 1, 0, 2, 4 })[stype];
262cabdff1aSopenharmony_ci    if (ach == 1 && quant && freq == 2)
263cabdff1aSopenharmony_ci        ach = 2;
264cabdff1aSopenharmony_ci
265cabdff1aSopenharmony_ci    /* Dynamic handling of the audio streams in DV */
266cabdff1aSopenharmony_ci    for (i = 0; i < ach; i++) {
267cabdff1aSopenharmony_ci        if (!c->ast[i]) {
268cabdff1aSopenharmony_ci            c->ast[i] = avformat_new_stream(c->fctx, NULL);
269cabdff1aSopenharmony_ci            if (!c->ast[i])
270cabdff1aSopenharmony_ci                break;
271cabdff1aSopenharmony_ci            avpriv_set_pts_info(c->ast[i], 64, c->sys->time_base.num, c->sys->time_base.den);
272cabdff1aSopenharmony_ci            c->ast[i]->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
273cabdff1aSopenharmony_ci            c->ast[i]->codecpar->codec_id   = AV_CODEC_ID_PCM_S16LE;
274cabdff1aSopenharmony_ci
275cabdff1aSopenharmony_ci            c->audio_pkt[i].size         = 0;
276cabdff1aSopenharmony_ci            c->audio_pkt[i].data         = c->audio_buf[i];
277cabdff1aSopenharmony_ci            c->audio_pkt[i].stream_index = c->ast[i]->index;
278cabdff1aSopenharmony_ci            c->audio_pkt[i].flags       |= AV_PKT_FLAG_KEY;
279cabdff1aSopenharmony_ci            c->audio_pkt[i].pts          = AV_NOPTS_VALUE;
280cabdff1aSopenharmony_ci            c->audio_pkt[i].duration     = 0;
281cabdff1aSopenharmony_ci            c->audio_pkt[i].pos          = -1;
282cabdff1aSopenharmony_ci        }
283cabdff1aSopenharmony_ci        c->ast[i]->codecpar->sample_rate    = dv_audio_frequency[freq];
284cabdff1aSopenharmony_ci        c->ast[i]->codecpar->ch_layout      = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
285cabdff1aSopenharmony_ci        c->ast[i]->codecpar->bit_rate       = 2 * dv_audio_frequency[freq] * 16;
286cabdff1aSopenharmony_ci        c->ast[i]->start_time            = 0;
287cabdff1aSopenharmony_ci    }
288cabdff1aSopenharmony_ci    c->ach = i;
289cabdff1aSopenharmony_ci
290cabdff1aSopenharmony_ci    return (c->sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */
291cabdff1aSopenharmony_ci}
292cabdff1aSopenharmony_ci
293cabdff1aSopenharmony_cistatic int dv_extract_video_info(DVDemuxContext *c, const uint8_t *frame)
294cabdff1aSopenharmony_ci{
295cabdff1aSopenharmony_ci    const uint8_t *vsc_pack;
296cabdff1aSopenharmony_ci    AVCodecParameters *par;
297cabdff1aSopenharmony_ci    int apt, is16_9;
298cabdff1aSopenharmony_ci
299cabdff1aSopenharmony_ci    par = c->vst->codecpar;
300cabdff1aSopenharmony_ci
301cabdff1aSopenharmony_ci    avpriv_set_pts_info(c->vst, 64, c->sys->time_base.num,
302cabdff1aSopenharmony_ci                        c->sys->time_base.den);
303cabdff1aSopenharmony_ci    c->vst->avg_frame_rate = av_inv_q(c->vst->time_base);
304cabdff1aSopenharmony_ci
305cabdff1aSopenharmony_ci    /* finding out SAR is a little bit messy */
306cabdff1aSopenharmony_ci    vsc_pack = dv_extract_pack(frame, dv_video_control);
307cabdff1aSopenharmony_ci    apt      = frame[4] & 0x07;
308cabdff1aSopenharmony_ci    is16_9   = (vsc_pack && ((vsc_pack[2] & 0x07) == 0x02 ||
309cabdff1aSopenharmony_ci                             (!apt && (vsc_pack[2] & 0x07) == 0x07)));
310cabdff1aSopenharmony_ci    c->vst->sample_aspect_ratio = c->sys->sar[is16_9];
311cabdff1aSopenharmony_ci    par->bit_rate = av_rescale_q(c->sys->frame_size,
312cabdff1aSopenharmony_ci                                   (AVRational) { 8, 1 },
313cabdff1aSopenharmony_ci                                   c->sys->time_base);
314cabdff1aSopenharmony_ci    return c->sys->frame_size;
315cabdff1aSopenharmony_ci}
316cabdff1aSopenharmony_ci
317cabdff1aSopenharmony_cistatic int dv_extract_timecode(DVDemuxContext* c, const uint8_t* frame, char *tc)
318cabdff1aSopenharmony_ci{
319cabdff1aSopenharmony_ci    const uint8_t *tc_pack;
320cabdff1aSopenharmony_ci
321cabdff1aSopenharmony_ci    // For PAL systems, drop frame bit is replaced by an arbitrary
322cabdff1aSopenharmony_ci    // bit so its value should not be considered. Drop frame timecode
323cabdff1aSopenharmony_ci    // is only relevant for NTSC systems.
324cabdff1aSopenharmony_ci    int prevent_df = c->sys->ltc_divisor == 25 || c->sys->ltc_divisor == 50;
325cabdff1aSopenharmony_ci
326cabdff1aSopenharmony_ci    tc_pack = dv_extract_pack(frame, dv_timecode);
327cabdff1aSopenharmony_ci    if (!tc_pack)
328cabdff1aSopenharmony_ci        return 0;
329cabdff1aSopenharmony_ci    av_timecode_make_smpte_tc_string2(tc, av_inv_q(c->sys->time_base), AV_RB32(tc_pack + 1), prevent_df, 1);
330cabdff1aSopenharmony_ci    return 1;
331cabdff1aSopenharmony_ci}
332cabdff1aSopenharmony_ci
333cabdff1aSopenharmony_ci/* The following 3 functions constitute our interface to the world */
334cabdff1aSopenharmony_ci
335cabdff1aSopenharmony_cistatic int dv_init_demux(AVFormatContext *s, DVDemuxContext *c)
336cabdff1aSopenharmony_ci{
337cabdff1aSopenharmony_ci    c->vst = avformat_new_stream(s, NULL);
338cabdff1aSopenharmony_ci    if (!c->vst)
339cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
340cabdff1aSopenharmony_ci
341cabdff1aSopenharmony_ci    c->fctx                   = s;
342cabdff1aSopenharmony_ci    c->vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
343cabdff1aSopenharmony_ci    c->vst->codecpar->codec_id   = AV_CODEC_ID_DVVIDEO;
344cabdff1aSopenharmony_ci    c->vst->codecpar->bit_rate   = 25000000;
345cabdff1aSopenharmony_ci    c->vst->start_time        = 0;
346cabdff1aSopenharmony_ci
347cabdff1aSopenharmony_ci    /* Audio streams are added later as they are encountered. */
348cabdff1aSopenharmony_ci    s->ctx_flags |= AVFMTCTX_NOHEADER;
349cabdff1aSopenharmony_ci
350cabdff1aSopenharmony_ci    return 0;
351cabdff1aSopenharmony_ci}
352cabdff1aSopenharmony_ci
353cabdff1aSopenharmony_ciDVDemuxContext *avpriv_dv_init_demux(AVFormatContext *s)
354cabdff1aSopenharmony_ci{
355cabdff1aSopenharmony_ci    DVDemuxContext *c;
356cabdff1aSopenharmony_ci
357cabdff1aSopenharmony_ci    c = av_mallocz(sizeof(DVDemuxContext));
358cabdff1aSopenharmony_ci    if (!c)
359cabdff1aSopenharmony_ci        return NULL;
360cabdff1aSopenharmony_ci
361cabdff1aSopenharmony_ci    if (dv_init_demux(s, c)) {
362cabdff1aSopenharmony_ci        av_free(c);
363cabdff1aSopenharmony_ci        return NULL;
364cabdff1aSopenharmony_ci    }
365cabdff1aSopenharmony_ci
366cabdff1aSopenharmony_ci    return c;
367cabdff1aSopenharmony_ci}
368cabdff1aSopenharmony_ci
369cabdff1aSopenharmony_ciint avpriv_dv_get_packet(DVDemuxContext *c, AVPacket *pkt)
370cabdff1aSopenharmony_ci{
371cabdff1aSopenharmony_ci    int size = -1;
372cabdff1aSopenharmony_ci    int i;
373cabdff1aSopenharmony_ci
374cabdff1aSopenharmony_ci    for (i = 0; i < c->ach; i++) {
375cabdff1aSopenharmony_ci        if (c->ast[i] && c->audio_pkt[i].size) {
376cabdff1aSopenharmony_ci            pkt->size         = c->audio_pkt[i].size;
377cabdff1aSopenharmony_ci            pkt->data         = c->audio_pkt[i].data;
378cabdff1aSopenharmony_ci            pkt->stream_index = c->audio_pkt[i].stream_index;
379cabdff1aSopenharmony_ci            pkt->flags        = c->audio_pkt[i].flags;
380cabdff1aSopenharmony_ci            pkt->pts          = c->audio_pkt[i].pts;
381cabdff1aSopenharmony_ci            pkt->duration     = c->audio_pkt[i].duration;
382cabdff1aSopenharmony_ci            pkt->pos          = c->audio_pkt[i].pos;
383cabdff1aSopenharmony_ci
384cabdff1aSopenharmony_ci            c->audio_pkt[i].size = 0;
385cabdff1aSopenharmony_ci            size                 = pkt->size;
386cabdff1aSopenharmony_ci            break;
387cabdff1aSopenharmony_ci        }
388cabdff1aSopenharmony_ci    }
389cabdff1aSopenharmony_ci
390cabdff1aSopenharmony_ci    return size;
391cabdff1aSopenharmony_ci}
392cabdff1aSopenharmony_ci
393cabdff1aSopenharmony_ciint avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,
394cabdff1aSopenharmony_ci                             uint8_t *buf, int buf_size, int64_t pos)
395cabdff1aSopenharmony_ci{
396cabdff1aSopenharmony_ci    int size, i;
397cabdff1aSopenharmony_ci    uint8_t *ppcm[5] = { 0 };
398cabdff1aSopenharmony_ci
399cabdff1aSopenharmony_ci    if (buf_size < DV_PROFILE_BYTES ||
400cabdff1aSopenharmony_ci        !(c->sys = av_dv_frame_profile(c->sys, buf, buf_size)) ||
401cabdff1aSopenharmony_ci        buf_size < c->sys->frame_size) {
402cabdff1aSopenharmony_ci        return -1;   /* Broken frame, or not enough data */
403cabdff1aSopenharmony_ci    }
404cabdff1aSopenharmony_ci
405cabdff1aSopenharmony_ci    /* Queueing audio packet */
406cabdff1aSopenharmony_ci    /* FIXME: in case of no audio/bad audio we have to do something */
407cabdff1aSopenharmony_ci    size = dv_extract_audio_info(c, buf);
408cabdff1aSopenharmony_ci    for (i = 0; i < c->ach; i++) {
409cabdff1aSopenharmony_ci        c->audio_pkt[i].pos  = pos;
410cabdff1aSopenharmony_ci        c->audio_pkt[i].size = size;
411cabdff1aSopenharmony_ci        c->audio_pkt[i].pts  = (c->sys->height == 720) ? (c->frames & ~1) : c->frames;
412cabdff1aSopenharmony_ci        c->audio_pkt[i].duration = 1;
413cabdff1aSopenharmony_ci        ppcm[i] = c->audio_buf[i];
414cabdff1aSopenharmony_ci    }
415cabdff1aSopenharmony_ci    if (c->ach)
416cabdff1aSopenharmony_ci        dv_extract_audio(buf, ppcm, c->sys);
417cabdff1aSopenharmony_ci
418cabdff1aSopenharmony_ci    /* We work with 720p frames split in half, thus even frames have
419cabdff1aSopenharmony_ci     * channels 0,1 and odd 2,3. */
420cabdff1aSopenharmony_ci    if (c->sys->height == 720) {
421cabdff1aSopenharmony_ci        if (buf[1] & 0x0C) {
422cabdff1aSopenharmony_ci            c->audio_pkt[2].size = c->audio_pkt[3].size = 0;
423cabdff1aSopenharmony_ci        } else {
424cabdff1aSopenharmony_ci            c->audio_pkt[0].size = c->audio_pkt[1].size = 0;
425cabdff1aSopenharmony_ci        }
426cabdff1aSopenharmony_ci    }
427cabdff1aSopenharmony_ci
428cabdff1aSopenharmony_ci    /* Now it's time to return video packet */
429cabdff1aSopenharmony_ci    size = dv_extract_video_info(c, buf);
430cabdff1aSopenharmony_ci    pkt->data         = buf;
431cabdff1aSopenharmony_ci    pkt->pos          = pos;
432cabdff1aSopenharmony_ci    pkt->size         = size;
433cabdff1aSopenharmony_ci    pkt->flags       |= AV_PKT_FLAG_KEY;
434cabdff1aSopenharmony_ci    pkt->stream_index = c->vst->index;
435cabdff1aSopenharmony_ci    pkt->pts          = c->frames;
436cabdff1aSopenharmony_ci
437cabdff1aSopenharmony_ci    c->frames++;
438cabdff1aSopenharmony_ci
439cabdff1aSopenharmony_ci    return size;
440cabdff1aSopenharmony_ci}
441cabdff1aSopenharmony_ci
442cabdff1aSopenharmony_cistatic int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c,
443cabdff1aSopenharmony_ci                               int64_t timestamp, int flags)
444cabdff1aSopenharmony_ci{
445cabdff1aSopenharmony_ci    // FIXME: sys may be wrong if last dv_read_packet() failed (buffer is junk)
446cabdff1aSopenharmony_ci    FFFormatContext *const si = ffformatcontext(s);
447cabdff1aSopenharmony_ci    const int frame_size = c->sys->frame_size;
448cabdff1aSopenharmony_ci    int64_t offset;
449cabdff1aSopenharmony_ci    int64_t size       = avio_size(s->pb) - si->data_offset;
450cabdff1aSopenharmony_ci    int64_t max_offset = ((size - 1) / frame_size) * frame_size;
451cabdff1aSopenharmony_ci
452cabdff1aSopenharmony_ci    offset = frame_size * timestamp;
453cabdff1aSopenharmony_ci
454cabdff1aSopenharmony_ci    if (size >= 0 && offset > max_offset)
455cabdff1aSopenharmony_ci        offset = max_offset;
456cabdff1aSopenharmony_ci    else if (offset < 0)
457cabdff1aSopenharmony_ci        offset = 0;
458cabdff1aSopenharmony_ci
459cabdff1aSopenharmony_ci    return offset + si->data_offset;
460cabdff1aSopenharmony_ci}
461cabdff1aSopenharmony_ci
462cabdff1aSopenharmony_civoid ff_dv_offset_reset(DVDemuxContext *c, int64_t frame_offset)
463cabdff1aSopenharmony_ci{
464cabdff1aSopenharmony_ci    c->frames = frame_offset;
465cabdff1aSopenharmony_ci    c->audio_pkt[0].size = c->audio_pkt[1].size = 0;
466cabdff1aSopenharmony_ci    c->audio_pkt[2].size = c->audio_pkt[3].size = 0;
467cabdff1aSopenharmony_ci}
468cabdff1aSopenharmony_ci
469cabdff1aSopenharmony_ci/************************************************************
470cabdff1aSopenharmony_ci * Implementation of the easiest DV storage of all -- raw DV.
471cabdff1aSopenharmony_ci ************************************************************/
472cabdff1aSopenharmony_ci
473cabdff1aSopenharmony_citypedef struct RawDVContext {
474cabdff1aSopenharmony_ci    DVDemuxContext  dv_demux;
475cabdff1aSopenharmony_ci    uint8_t         buf[DV_MAX_FRAME_SIZE];
476cabdff1aSopenharmony_ci} RawDVContext;
477cabdff1aSopenharmony_ci
478cabdff1aSopenharmony_cistatic int dv_read_timecode(AVFormatContext *s) {
479cabdff1aSopenharmony_ci    int ret;
480cabdff1aSopenharmony_ci    char timecode[AV_TIMECODE_STR_SIZE];
481cabdff1aSopenharmony_ci    int64_t pos = avio_tell(s->pb);
482cabdff1aSopenharmony_ci
483cabdff1aSopenharmony_ci    // Read 3 DIF blocks: Header block and 2 Subcode blocks.
484cabdff1aSopenharmony_ci#define PARTIAL_FRAME_SIZE (3 * 80)
485cabdff1aSopenharmony_ci    uint8_t partial_frame[PARTIAL_FRAME_SIZE];
486cabdff1aSopenharmony_ci    RawDVContext *c = s->priv_data;
487cabdff1aSopenharmony_ci
488cabdff1aSopenharmony_ci    ret = avio_read(s->pb, partial_frame, PARTIAL_FRAME_SIZE);
489cabdff1aSopenharmony_ci    if (ret < 0)
490cabdff1aSopenharmony_ci        goto finish;
491cabdff1aSopenharmony_ci
492cabdff1aSopenharmony_ci    if (ret < PARTIAL_FRAME_SIZE) {
493cabdff1aSopenharmony_ci        ret = -1;
494cabdff1aSopenharmony_ci        goto finish;
495cabdff1aSopenharmony_ci    }
496cabdff1aSopenharmony_ci
497cabdff1aSopenharmony_ci    ret = dv_extract_timecode(&c->dv_demux, partial_frame, timecode);
498cabdff1aSopenharmony_ci    if (ret)
499cabdff1aSopenharmony_ci        av_dict_set(&s->metadata, "timecode", timecode, 0);
500cabdff1aSopenharmony_ci    else
501cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Detected timecode is invalid\n");
502cabdff1aSopenharmony_ci
503cabdff1aSopenharmony_cifinish:
504cabdff1aSopenharmony_ci    avio_seek(s->pb, pos, SEEK_SET);
505cabdff1aSopenharmony_ci    return ret;
506cabdff1aSopenharmony_ci}
507cabdff1aSopenharmony_ci
508cabdff1aSopenharmony_cistatic int dv_read_header(AVFormatContext *s)
509cabdff1aSopenharmony_ci{
510cabdff1aSopenharmony_ci    unsigned state, marker_pos = 0;
511cabdff1aSopenharmony_ci    RawDVContext *c = s->priv_data;
512cabdff1aSopenharmony_ci    int ret;
513cabdff1aSopenharmony_ci
514cabdff1aSopenharmony_ci    if ((ret = dv_init_demux(s, &c->dv_demux)) < 0)
515cabdff1aSopenharmony_ci        return ret;
516cabdff1aSopenharmony_ci
517cabdff1aSopenharmony_ci    state = avio_rb32(s->pb);
518cabdff1aSopenharmony_ci    while ((state & 0xffffff7f) != 0x1f07003f) {
519cabdff1aSopenharmony_ci        if (avio_feof(s->pb)) {
520cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Cannot find DV header.\n");
521cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
522cabdff1aSopenharmony_ci        }
523cabdff1aSopenharmony_ci        if (state == 0x003f0700 || state == 0xff3f0700)
524cabdff1aSopenharmony_ci            marker_pos = avio_tell(s->pb);
525cabdff1aSopenharmony_ci        if (state == 0xff3f0701 && avio_tell(s->pb) - marker_pos == 80) {
526cabdff1aSopenharmony_ci            avio_seek(s->pb, -163, SEEK_CUR);
527cabdff1aSopenharmony_ci            state = avio_rb32(s->pb);
528cabdff1aSopenharmony_ci            break;
529cabdff1aSopenharmony_ci        }
530cabdff1aSopenharmony_ci        state = (state << 8) | avio_r8(s->pb);
531cabdff1aSopenharmony_ci    }
532cabdff1aSopenharmony_ci    AV_WB32(c->buf, state);
533cabdff1aSopenharmony_ci
534cabdff1aSopenharmony_ci    if (avio_read(s->pb, c->buf + 4, DV_PROFILE_BYTES - 4) != DV_PROFILE_BYTES - 4 ||
535cabdff1aSopenharmony_ci        avio_seek(s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0) {
536cabdff1aSopenharmony_ci        return AVERROR(EIO);
537cabdff1aSopenharmony_ci    }
538cabdff1aSopenharmony_ci
539cabdff1aSopenharmony_ci    c->dv_demux.sys = av_dv_frame_profile(c->dv_demux.sys,
540cabdff1aSopenharmony_ci                                           c->buf,
541cabdff1aSopenharmony_ci                                           DV_PROFILE_BYTES);
542cabdff1aSopenharmony_ci    if (!c->dv_demux.sys) {
543cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR,
544cabdff1aSopenharmony_ci               "Can't determine profile of DV input stream.\n");
545cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
546cabdff1aSopenharmony_ci    }
547cabdff1aSopenharmony_ci
548cabdff1aSopenharmony_ci    s->bit_rate = av_rescale_q(c->dv_demux.sys->frame_size,
549cabdff1aSopenharmony_ci                               (AVRational) { 8, 1 },
550cabdff1aSopenharmony_ci                               c->dv_demux.sys->time_base);
551cabdff1aSopenharmony_ci
552cabdff1aSopenharmony_ci    if (s->pb->seekable & AVIO_SEEKABLE_NORMAL)
553cabdff1aSopenharmony_ci        dv_read_timecode(s);
554cabdff1aSopenharmony_ci
555cabdff1aSopenharmony_ci    return 0;
556cabdff1aSopenharmony_ci}
557cabdff1aSopenharmony_ci
558cabdff1aSopenharmony_cistatic int dv_read_packet(AVFormatContext *s, AVPacket *pkt)
559cabdff1aSopenharmony_ci{
560cabdff1aSopenharmony_ci    int size;
561cabdff1aSopenharmony_ci    RawDVContext *c = s->priv_data;
562cabdff1aSopenharmony_ci
563cabdff1aSopenharmony_ci    size = avpriv_dv_get_packet(&c->dv_demux, pkt);
564cabdff1aSopenharmony_ci
565cabdff1aSopenharmony_ci    if (size < 0) {
566cabdff1aSopenharmony_ci        int ret;
567cabdff1aSopenharmony_ci        int64_t pos = avio_tell(s->pb);
568cabdff1aSopenharmony_ci        if (!c->dv_demux.sys)
569cabdff1aSopenharmony_ci            return AVERROR(EIO);
570cabdff1aSopenharmony_ci        size = c->dv_demux.sys->frame_size;
571cabdff1aSopenharmony_ci        ret = avio_read(s->pb, c->buf, size);
572cabdff1aSopenharmony_ci        if (ret < 0) {
573cabdff1aSopenharmony_ci            return ret;
574cabdff1aSopenharmony_ci        } else if (ret == 0) {
575cabdff1aSopenharmony_ci            return AVERROR(EIO);
576cabdff1aSopenharmony_ci        }
577cabdff1aSopenharmony_ci
578cabdff1aSopenharmony_ci        size = avpriv_dv_produce_packet(&c->dv_demux, pkt, c->buf, size, pos);
579cabdff1aSopenharmony_ci    }
580cabdff1aSopenharmony_ci
581cabdff1aSopenharmony_ci    return size;
582cabdff1aSopenharmony_ci}
583cabdff1aSopenharmony_ci
584cabdff1aSopenharmony_cistatic int dv_read_seek(AVFormatContext *s, int stream_index,
585cabdff1aSopenharmony_ci                        int64_t timestamp, int flags)
586cabdff1aSopenharmony_ci{
587cabdff1aSopenharmony_ci    RawDVContext *r   = s->priv_data;
588cabdff1aSopenharmony_ci    DVDemuxContext *c = &r->dv_demux;
589cabdff1aSopenharmony_ci    int64_t offset    = dv_frame_offset(s, c, timestamp, flags);
590cabdff1aSopenharmony_ci
591cabdff1aSopenharmony_ci    if (avio_seek(s->pb, offset, SEEK_SET) < 0)
592cabdff1aSopenharmony_ci        return -1;
593cabdff1aSopenharmony_ci
594cabdff1aSopenharmony_ci    ff_dv_offset_reset(c, offset / c->sys->frame_size);
595cabdff1aSopenharmony_ci    return 0;
596cabdff1aSopenharmony_ci}
597cabdff1aSopenharmony_ci
598cabdff1aSopenharmony_cistatic int dv_probe(const AVProbeData *p)
599cabdff1aSopenharmony_ci{
600cabdff1aSopenharmony_ci    unsigned marker_pos = 0;
601cabdff1aSopenharmony_ci    int i;
602cabdff1aSopenharmony_ci    int matches           = 0;
603cabdff1aSopenharmony_ci    int firstmatch        = 0;
604cabdff1aSopenharmony_ci    int secondary_matches = 0;
605cabdff1aSopenharmony_ci
606cabdff1aSopenharmony_ci    if (p->buf_size < 5)
607cabdff1aSopenharmony_ci        return 0;
608cabdff1aSopenharmony_ci
609cabdff1aSopenharmony_ci    for (i = 0; i < p->buf_size-4; i++) {
610cabdff1aSopenharmony_ci        unsigned state = AV_RB32(p->buf+i);
611cabdff1aSopenharmony_ci        if ((state & 0x0007f840) == 0x00070000) {
612cabdff1aSopenharmony_ci            // any section header, also with seq/chan num != 0,
613cabdff1aSopenharmony_ci            // should appear around every 12000 bytes, at least 10 per frame
614cabdff1aSopenharmony_ci            if ((state & 0xff07ff7f) == 0x1f07003f) {
615cabdff1aSopenharmony_ci                secondary_matches++;
616cabdff1aSopenharmony_ci                if ((state & 0xffffff7f) == 0x1f07003f) {
617cabdff1aSopenharmony_ci                    matches++;
618cabdff1aSopenharmony_ci                    if (!i)
619cabdff1aSopenharmony_ci                        firstmatch = 1;
620cabdff1aSopenharmony_ci                }
621cabdff1aSopenharmony_ci            }
622cabdff1aSopenharmony_ci            if (state == 0x003f0700 || state == 0xff3f0700)
623cabdff1aSopenharmony_ci                marker_pos = i;
624cabdff1aSopenharmony_ci            if (state == 0xff3f0701 && i - marker_pos == 80)
625cabdff1aSopenharmony_ci                matches++;
626cabdff1aSopenharmony_ci        }
627cabdff1aSopenharmony_ci    }
628cabdff1aSopenharmony_ci
629cabdff1aSopenharmony_ci    if (matches && p->buf_size / matches < 1024 * 1024) {
630cabdff1aSopenharmony_ci        if (matches > 4 || firstmatch ||
631cabdff1aSopenharmony_ci            (secondary_matches >= 10 &&
632cabdff1aSopenharmony_ci             p->buf_size / secondary_matches < 24000))
633cabdff1aSopenharmony_ci            // not max to avoid dv in mov to match
634cabdff1aSopenharmony_ci            return AVPROBE_SCORE_MAX * 3 / 4;
635cabdff1aSopenharmony_ci        return AVPROBE_SCORE_MAX / 4;
636cabdff1aSopenharmony_ci    }
637cabdff1aSopenharmony_ci    return 0;
638cabdff1aSopenharmony_ci}
639cabdff1aSopenharmony_ci
640cabdff1aSopenharmony_ciconst AVInputFormat ff_dv_demuxer = {
641cabdff1aSopenharmony_ci    .name           = "dv",
642cabdff1aSopenharmony_ci    .long_name      = NULL_IF_CONFIG_SMALL("DV (Digital Video)"),
643cabdff1aSopenharmony_ci    .priv_data_size = sizeof(RawDVContext),
644cabdff1aSopenharmony_ci    .read_probe     = dv_probe,
645cabdff1aSopenharmony_ci    .read_header    = dv_read_header,
646cabdff1aSopenharmony_ci    .read_packet    = dv_read_packet,
647cabdff1aSopenharmony_ci    .read_seek      = dv_read_seek,
648cabdff1aSopenharmony_ci    .extensions     = "dv,dif",
649cabdff1aSopenharmony_ci};
650