diff options
author | Roman Shaposhnik <roman@shaposhnik.org> | 2008-08-28 22:41:00 +0000 |
---|---|---|
committer | Roman Shaposhnik <roman@shaposhnik.org> | 2008-08-28 22:41:00 +0000 |
commit | f8007a14734ff9fc8a4dd0d0194ab2c645f72578 (patch) | |
tree | 4c1ed13cb5931ab5690c4680f71b3a76bc9e55f1 /libavformat | |
parent | 42f72a3ac467f15bfa90b52af92ee0458564365f (diff) | |
download | ffmpeg-f8007a14734ff9fc8a4dd0d0194ab2c645f72578.tar.gz |
Intial implementation of the DV100 (AKA DVCPRO HD) decoder and demuxer as
specified in SMPTE 370M
Originally committed as revision 15010 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/dv.c | 48 | ||||
-rw-r--r-- | libavformat/isom.c | 8 |
2 files changed, 42 insertions, 14 deletions
diff --git a/libavformat/dv.c b/libavformat/dv.c index c60154738c..815caf866d 100644 --- a/libavformat/dv.c +++ b/libavformat/dv.c @@ -8,8 +8,9 @@ * Raw DV format * Copyright (c) 2002 Fabrice Bellard. * - * 50 Mbps (DVCPRO50) support + * 50 Mbps (DVCPRO50) and 100 Mbps (DVCPRO HD) support * Copyright (c) 2006 Daniel Maas <dmaas@maasdigital.com> + * Funded by BBC Research & Development * * This file is part of FFmpeg. * @@ -36,9 +37,9 @@ struct DVDemuxContext { const DVprofile* sys; /* Current DV profile. E.g.: 525/60, 625/50 */ AVFormatContext* fctx; AVStream* vst; - AVStream* ast[2]; - AVPacket audio_pkt[2]; - uint8_t audio_buf[2][8192]; + AVStream* ast[4]; + AVPacket audio_pkt[4]; + uint8_t audio_buf[4][8192]; int ach; int frames; uint64_t abytes; @@ -98,12 +99,13 @@ static const uint8_t* dv_extract_pack(uint8_t* frame, enum dv_pack_type t) * 3. Audio is always returned as 16bit linear samples: 12bit nonlinear samples * are converted into 16bit linear ones. */ -static int dv_extract_audio(uint8_t* frame, uint8_t* pcm, uint8_t* pcm2, +static int dv_extract_audio(uint8_t* frame, uint8_t* ppcm[4], const DVprofile *sys) { int size, chan, i, j, d, of, smpls, freq, quant, half_ch; uint16_t lc, rc; const uint8_t* as_pack; + uint8_t *pcm, ipcm; as_pack = dv_extract_pack(frame, dv_audio_source); if (!as_pack) /* No audio ? */ @@ -119,6 +121,10 @@ static int dv_extract_audio(uint8_t* frame, uint8_t* pcm, uint8_t* pcm2, size = (sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */ half_ch = sys->difseg_size/2; + /* We work with 720p frames split in half, thus even frames have channels 0,1 and odd 2,3 */ + ipcm = (sys->height == 720 && ((frame[1]>>2)&0x3) == 0)?2:0; + pcm = ppcm[ipcm++]; + /* for each DIF channel */ for (chan = 0; chan < sys->n_difchan; chan++) { /* for each DIF segment */ @@ -126,10 +132,9 @@ static int dv_extract_audio(uint8_t* frame, uint8_t* pcm, uint8_t* pcm2, frame += 6 * 80; /* skip DIF segment header */ if (quant == 1 && i == half_ch) { /* next stereo channel (12bit mode only) */ - if (!pcm2) + pcm = ppcm[ipcm++]; + if (!pcm) break; - else - pcm = pcm2; } /* for each AV sequence */ @@ -170,10 +175,10 @@ static int dv_extract_audio(uint8_t* frame, uint8_t* pcm, uint8_t* pcm2, } } - /* next stereo channel (50Mbps only) */ - if(!pcm2) + /* next stereo channel (50Mbps and 100Mbps only) */ + pcm = ppcm[ipcm++]; + if (!pcm) break; - pcm = pcm2; } return size; @@ -196,6 +201,9 @@ static int dv_extract_audio_info(DVDemuxContext* c, uint8_t* frame) quant = as_pack[4] & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */ /* note: ach counts PAIRS of channels (i.e. stereo channels) */ + if (stype == 3) { + ach = 4; + } else ach = (stype == 2 || (quant && (freq == 2))) ? 2 : 1; /* Dynamic handling of the audio streams in DV */ @@ -310,6 +318,7 @@ int dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, uint8_t* buf, int buf_size) { int size, i; + uint8_t *ppcm[4] = {0}; if (buf_size < DV_PROFILE_BYTES || !(c->sys = dv_frame_profile(buf)) || @@ -323,10 +332,19 @@ int dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, for (i=0; i<c->ach; i++) { c->audio_pkt[i].size = size; c->audio_pkt[i].pts = c->abytes * 30000*8 / c->ast[i]->codec->bit_rate; + ppcm[i] = c->audio_buf[i]; } - dv_extract_audio(buf, c->audio_buf[0], c->audio_buf[1], c->sys); + dv_extract_audio(buf, ppcm, c->sys); c->abytes += size; + /* We work with 720p frames split in half, thus even frames have channels 0,1 and odd 2,3 */ + if (c->sys->height == 720) { + if (((buf[1]>>2)&0x3)) + c->audio_pkt[2].size = c->audio_pkt[3].size = 0; + else + c->audio_pkt[0].size = c->audio_pkt[1].size = 0; + } + /* Now it's time to return video packet */ size = dv_extract_video_info(c, buf); av_init_packet(pkt); @@ -366,6 +384,7 @@ void dv_offset_reset(DVDemuxContext *c, int64_t frame_offset) c->ast[0]->codec->bit_rate * (int64_t)c->sys->frame_rate_base, 8*c->sys->frame_rate); c->audio_pkt[0].size = c->audio_pkt[1].size = 0; + c->audio_pkt[2].size = c->audio_pkt[3].size = 0; } /************************************************************ @@ -391,6 +410,11 @@ static int dv_read_header(AVFormatContext *s, return AVERROR(EIO); c->dv_demux->sys = dv_frame_profile(c->buf); + if (!c->dv_demux->sys) { + av_log(s, AV_LOG_ERROR, "Can't determine profile of DV input stream.\n"); + return -1; + } + s->bit_rate = av_rescale(c->dv_demux->sys->frame_size * 8, c->dv_demux->sys->frame_rate, c->dv_demux->sys->frame_rate_base); diff --git a/libavformat/isom.c b/libavformat/isom.c index 35940201ab..bfe27354dd 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -87,8 +87,12 @@ const AVCodecTag codec_movvideo_tags[] = { { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'p') }, /* DVCPRO50 PAL produced by FCP */ { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'n') }, /* DVCPRO50 NTSC produced by FCP */ { CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, /* AVID DV */ - //{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '5') }, /* DVCPRO HD 50i produced by FCP */ - //{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '6') }, /* DVCPRO HD 60i produced by FCP */ + { CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', '1') }, /* AVID DV */ + { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'q') }, /* DVCPRO HD 720p50 */ + { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'p') }, /* DVCPRO HD 720p60 */ + { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '5') }, /* DVCPRO HD 50i produced by FCP */ + { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '6') }, /* DVCPRO HD 60i produced by FCP */ + { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '3') }, /* DVCPRO HD 30p produced by FCP */ { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') }, /* On2 VP3 */ { CODEC_ID_RPZA, MKTAG('r', 'p', 'z', 'a') }, /* Apple Video (RPZA) */ |