00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <time.h>
00032 #include "avformat.h"
00033 #include "libavcodec/dvdata.h"
00034 #include "libavutil/intreadwrite.h"
00035 #include "dv.h"
00036
00037 struct DVDemuxContext {
00038 const DVprofile* sys;
00039 AVFormatContext* fctx;
00040 AVStream* vst;
00041 AVStream* ast[4];
00042 AVPacket audio_pkt[4];
00043 uint8_t audio_buf[4][8192];
00044 int ach;
00045 int frames;
00046 uint64_t abytes;
00047 };
00048
00049 static inline uint16_t dv_audio_12to16(uint16_t sample)
00050 {
00051 uint16_t shift, result;
00052
00053 sample = (sample < 0x800) ? sample : sample | 0xf000;
00054 shift = (sample & 0xf00) >> 8;
00055
00056 if (shift < 0x2 || shift > 0xd) {
00057 result = sample;
00058 } else if (shift < 0x8) {
00059 shift--;
00060 result = (sample - (256 * shift)) << shift;
00061 } else {
00062 shift = 0xe - shift;
00063 result = ((sample + ((256 * shift) + 1)) << shift) - 1;
00064 }
00065
00066 return result;
00067 }
00068
00069
00070
00071
00072
00073
00074 static const uint8_t* dv_extract_pack(uint8_t* frame, enum dv_pack_type t)
00075 {
00076 int offs;
00077
00078 switch (t) {
00079 case dv_audio_source:
00080 offs = (80*6 + 80*16*3 + 3);
00081 break;
00082 case dv_audio_control:
00083 offs = (80*6 + 80*16*4 + 3);
00084 break;
00085 case dv_video_control:
00086 offs = (80*5 + 48 + 5);
00087 break;
00088 default:
00089 return NULL;
00090 }
00091
00092 return frame[offs] == t ? &frame[offs] : NULL;
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 static int dv_extract_audio(uint8_t* frame, uint8_t* ppcm[4],
00104 const DVprofile *sys)
00105 {
00106 int size, chan, i, j, d, of, smpls, freq, quant, half_ch;
00107 uint16_t lc, rc;
00108 const uint8_t* as_pack;
00109 uint8_t *pcm, ipcm;
00110
00111 as_pack = dv_extract_pack(frame, dv_audio_source);
00112 if (!as_pack)
00113 return 0;
00114
00115 smpls = as_pack[1] & 0x3f;
00116 freq = (as_pack[4] >> 3) & 0x07;
00117 quant = as_pack[4] & 0x07;
00118
00119 if (quant > 1)
00120 return -1;
00121
00122 if (freq >= FF_ARRAY_ELEMS(dv_audio_frequency))
00123 return AVERROR_INVALIDDATA;
00124
00125 size = (sys->audio_min_samples[freq] + smpls) * 4;
00126 half_ch = sys->difseg_size / 2;
00127
00128
00129
00130 ipcm = (sys->height == 720 && !(frame[1] & 0x0C)) ? 2 : 0;
00131
00132
00133 for (chan = 0; chan < sys->n_difchan; chan++) {
00134
00135 pcm = ppcm[ipcm++];
00136 if (!pcm)
00137 break;
00138
00139
00140 for (i = 0; i < sys->difseg_size; i++) {
00141 frame += 6 * 80;
00142 if (quant == 1 && i == half_ch) {
00143
00144 pcm = ppcm[ipcm++];
00145 if (!pcm)
00146 break;
00147 }
00148
00149
00150 for (j = 0; j < 9; j++) {
00151 for (d = 8; d < 80; d += 2) {
00152 if (quant == 0) {
00153 of = sys->audio_shuffle[i][j] + (d - 8) / 2 * sys->audio_stride;
00154 if (of*2 >= size)
00155 continue;
00156
00157 pcm[of*2] = frame[d+1];
00158 pcm[of*2+1] = frame[d];
00159 if (pcm[of*2+1] == 0x80 && pcm[of*2] == 0x00)
00160 pcm[of*2+1] = 0;
00161 } else {
00162 lc = ((uint16_t)frame[d] << 4) |
00163 ((uint16_t)frame[d+2] >> 4);
00164 rc = ((uint16_t)frame[d+1] << 4) |
00165 ((uint16_t)frame[d+2] & 0x0f);
00166 lc = (lc == 0x800 ? 0 : dv_audio_12to16(lc));
00167 rc = (rc == 0x800 ? 0 : dv_audio_12to16(rc));
00168
00169 of = sys->audio_shuffle[i%half_ch][j] + (d - 8) / 3 * sys->audio_stride;
00170 if (of*2 >= size)
00171 continue;
00172
00173 pcm[of*2] = lc & 0xff;
00174 pcm[of*2+1] = lc >> 8;
00175 of = sys->audio_shuffle[i%half_ch+half_ch][j] +
00176 (d - 8) / 3 * sys->audio_stride;
00177 pcm[of*2] = rc & 0xff;
00178 pcm[of*2+1] = rc >> 8;
00179 ++d;
00180 }
00181 }
00182
00183 frame += 16 * 80;
00184 }
00185 }
00186 }
00187
00188 return size;
00189 }
00190
00191 static int dv_extract_audio_info(DVDemuxContext* c, uint8_t* frame)
00192 {
00193 const uint8_t* as_pack;
00194 int freq, stype, smpls, quant, i, ach;
00195
00196 as_pack = dv_extract_pack(frame, dv_audio_source);
00197 if (!as_pack || !c->sys) {
00198 c->ach = 0;
00199 return 0;
00200 }
00201
00202 smpls = as_pack[1] & 0x3f;
00203 freq = (as_pack[4] >> 3) & 0x07;
00204 stype = (as_pack[3] & 0x1f);
00205 quant = as_pack[4] & 0x07;
00206
00207 if (freq >= FF_ARRAY_ELEMS(dv_audio_frequency)) {
00208 av_log(c->fctx, AV_LOG_ERROR,
00209 "Unrecognized audio sample rate index (%d)\n", freq);
00210 return 0;
00211 }
00212
00213 if (stype > 3) {
00214 av_log(c->fctx, AV_LOG_ERROR, "stype %d is invalid\n", stype);
00215 c->ach = 0;
00216 return 0;
00217 }
00218
00219
00220 ach = ((int[4]){ 1, 0, 2, 4})[stype];
00221 if (ach == 1 && quant && freq == 2)
00222 ach = 2;
00223
00224
00225 for (i = 0; i < ach; i++) {
00226 if (!c->ast[i]) {
00227 c->ast[i] = av_new_stream(c->fctx, 0);
00228 if (!c->ast[i])
00229 break;
00230 av_set_pts_info(c->ast[i], 64, 1, 30000);
00231 c->ast[i]->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00232 c->ast[i]->codec->codec_id = CODEC_ID_PCM_S16LE;
00233
00234 av_init_packet(&c->audio_pkt[i]);
00235 c->audio_pkt[i].size = 0;
00236 c->audio_pkt[i].data = c->audio_buf[i];
00237 c->audio_pkt[i].stream_index = c->ast[i]->index;
00238 c->audio_pkt[i].flags |= AV_PKT_FLAG_KEY;
00239 }
00240 c->ast[i]->codec->sample_rate = dv_audio_frequency[freq];
00241 c->ast[i]->codec->channels = 2;
00242 c->ast[i]->codec->bit_rate = 2 * dv_audio_frequency[freq] * 16;
00243 c->ast[i]->start_time = 0;
00244 }
00245 c->ach = i;
00246
00247 return (c->sys->audio_min_samples[freq] + smpls) * 4; ;
00248 }
00249
00250 static int dv_extract_video_info(DVDemuxContext *c, uint8_t* frame)
00251 {
00252 const uint8_t* vsc_pack;
00253 AVCodecContext* avctx;
00254 int apt, is16_9;
00255 int size = 0;
00256
00257 if (c->sys) {
00258 avctx = c->vst->codec;
00259
00260 av_set_pts_info(c->vst, 64, c->sys->time_base.num,
00261 c->sys->time_base.den);
00262 avctx->time_base= c->sys->time_base;
00263 if (!avctx->width){
00264 avctx->width = c->sys->width;
00265 avctx->height = c->sys->height;
00266 }
00267 avctx->pix_fmt = c->sys->pix_fmt;
00268
00269
00270 vsc_pack = dv_extract_pack(frame, dv_video_control);
00271 apt = frame[4] & 0x07;
00272 is16_9 = (vsc_pack && ((vsc_pack[2] & 0x07) == 0x02 ||
00273 (!apt && (vsc_pack[2] & 0x07) == 0x07)));
00274 c->vst->sample_aspect_ratio = c->sys->sar[is16_9];
00275 avctx->bit_rate = av_rescale_q(c->sys->frame_size, (AVRational){8,1},
00276 c->sys->time_base);
00277 size = c->sys->frame_size;
00278 }
00279 return size;
00280 }
00281
00282
00283
00284
00285
00286 DVDemuxContext* dv_init_demux(AVFormatContext *s)
00287 {
00288 DVDemuxContext *c;
00289
00290 c = av_mallocz(sizeof(DVDemuxContext));
00291 if (!c)
00292 return NULL;
00293
00294 c->vst = av_new_stream(s, 0);
00295 if (!c->vst) {
00296 av_free(c);
00297 return NULL;
00298 }
00299
00300 c->sys = NULL;
00301 c->fctx = s;
00302 memset(c->ast, 0, sizeof(c->ast));
00303 c->ach = 0;
00304 c->frames = 0;
00305 c->abytes = 0;
00306
00307 c->vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00308 c->vst->codec->codec_id = CODEC_ID_DVVIDEO;
00309 c->vst->codec->bit_rate = 25000000;
00310 c->vst->start_time = 0;
00311
00312 return c;
00313 }
00314
00315 int dv_get_packet(DVDemuxContext *c, AVPacket *pkt)
00316 {
00317 int size = -1;
00318 int i;
00319
00320 for (i = 0; i < c->ach; i++) {
00321 if (c->ast[i] && c->audio_pkt[i].size) {
00322 *pkt = c->audio_pkt[i];
00323 c->audio_pkt[i].size = 0;
00324 size = pkt->size;
00325 break;
00326 }
00327 }
00328
00329 return size;
00330 }
00331
00332 int dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,
00333 uint8_t* buf, int buf_size, int64_t pos)
00334 {
00335 int size, i;
00336 uint8_t *ppcm[4] = {0};
00337
00338 if (buf_size < DV_PROFILE_BYTES ||
00339 !(c->sys = ff_dv_frame_profile(c->sys, buf, buf_size)) ||
00340 buf_size < c->sys->frame_size) {
00341 return -1;
00342 }
00343
00344
00345
00346 size = dv_extract_audio_info(c, buf);
00347 for (i = 0; i < c->ach; i++) {
00348 c->audio_pkt[i].pos = pos;
00349 c->audio_pkt[i].size = size;
00350 c->audio_pkt[i].pts = c->abytes * 30000*8 / c->ast[i]->codec->bit_rate;
00351 ppcm[i] = c->audio_buf[i];
00352 }
00353 if (c->ach)
00354 dv_extract_audio(buf, ppcm, c->sys);
00355
00356
00357
00358 if (c->sys->height == 720) {
00359 if (buf[1] & 0x0C) {
00360 c->audio_pkt[2].size = c->audio_pkt[3].size = 0;
00361 } else {
00362 c->audio_pkt[0].size = c->audio_pkt[1].size = 0;
00363 c->abytes += size;
00364 }
00365 } else {
00366 c->abytes += size;
00367 }
00368
00369
00370 size = dv_extract_video_info(c, buf);
00371 av_init_packet(pkt);
00372 pkt->data = buf;
00373 pkt->pos = pos;
00374 pkt->size = size;
00375 pkt->flags |= AV_PKT_FLAG_KEY;
00376 pkt->stream_index = c->vst->id;
00377 pkt->pts = c->frames;
00378
00379 c->frames++;
00380
00381 return size;
00382 }
00383
00384 static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c,
00385 int64_t timestamp, int flags)
00386 {
00387
00388 const DVprofile* sys = ff_dv_codec_profile(c->vst->codec);
00389 int64_t offset;
00390 int64_t size = avio_size(s->pb) - s->data_offset;
00391 int64_t max_offset = ((size-1) / sys->frame_size) * sys->frame_size;
00392
00393 offset = sys->frame_size * timestamp;
00394
00395 if (size >= 0 && offset > max_offset) offset = max_offset;
00396 else if (offset < 0) offset = 0;
00397
00398 return offset + s->data_offset;
00399 }
00400
00401 void dv_offset_reset(DVDemuxContext *c, int64_t frame_offset)
00402 {
00403 c->frames= frame_offset;
00404 if (c->ach)
00405 c->abytes= av_rescale_q(c->frames, c->sys->time_base,
00406 (AVRational){8, c->ast[0]->codec->bit_rate});
00407 c->audio_pkt[0].size = c->audio_pkt[1].size = 0;
00408 c->audio_pkt[2].size = c->audio_pkt[3].size = 0;
00409 }
00410
00411
00412
00413
00414
00415 typedef struct RawDVContext {
00416 DVDemuxContext* dv_demux;
00417 uint8_t buf[DV_MAX_FRAME_SIZE];
00418 } RawDVContext;
00419
00420 static int dv_read_header(AVFormatContext *s,
00421 AVFormatParameters *ap)
00422 {
00423 unsigned state, marker_pos = 0;
00424 RawDVContext *c = s->priv_data;
00425
00426 c->dv_demux = dv_init_demux(s);
00427 if (!c->dv_demux)
00428 return -1;
00429
00430 state = avio_rb32(s->pb);
00431 while ((state & 0xffffff7f) != 0x1f07003f) {
00432 if (url_feof(s->pb)) {
00433 av_log(s, AV_LOG_ERROR, "Cannot find DV header.\n");
00434 return -1;
00435 }
00436 if (state == 0x003f0700 || state == 0xff3f0700)
00437 marker_pos = avio_tell(s->pb);
00438 if (state == 0xff3f0701 && avio_tell(s->pb) - marker_pos == 80) {
00439 avio_seek(s->pb, -163, SEEK_CUR);
00440 state = avio_rb32(s->pb);
00441 break;
00442 }
00443 state = (state << 8) | avio_r8(s->pb);
00444 }
00445 AV_WB32(c->buf, state);
00446
00447 if (avio_read(s->pb, c->buf + 4, DV_PROFILE_BYTES - 4) <= 0 ||
00448 avio_seek(s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0)
00449 return AVERROR(EIO);
00450
00451 c->dv_demux->sys = ff_dv_frame_profile(c->dv_demux->sys, c->buf, DV_PROFILE_BYTES);
00452 if (!c->dv_demux->sys) {
00453 av_log(s, AV_LOG_ERROR, "Can't determine profile of DV input stream.\n");
00454 return -1;
00455 }
00456
00457 s->bit_rate = av_rescale_q(c->dv_demux->sys->frame_size, (AVRational){8,1},
00458 c->dv_demux->sys->time_base);
00459
00460 return 0;
00461 }
00462
00463
00464 static int dv_read_packet(AVFormatContext *s, AVPacket *pkt)
00465 {
00466 int size;
00467 RawDVContext *c = s->priv_data;
00468
00469 size = dv_get_packet(c->dv_demux, pkt);
00470
00471 if (size < 0) {
00472 int64_t pos = avio_tell(s->pb);
00473 if (!c->dv_demux->sys)
00474 return AVERROR(EIO);
00475 size = c->dv_demux->sys->frame_size;
00476 if (avio_read(s->pb, c->buf, size) <= 0)
00477 return AVERROR(EIO);
00478
00479 size = dv_produce_packet(c->dv_demux, pkt, c->buf, size, pos);
00480 }
00481
00482 return size;
00483 }
00484
00485 static int dv_read_seek(AVFormatContext *s, int stream_index,
00486 int64_t timestamp, int flags)
00487 {
00488 RawDVContext *r = s->priv_data;
00489 DVDemuxContext *c = r->dv_demux;
00490 int64_t offset = dv_frame_offset(s, c, timestamp, flags);
00491
00492 dv_offset_reset(c, offset / c->sys->frame_size);
00493
00494 offset = avio_seek(s->pb, offset, SEEK_SET);
00495 return (offset < 0) ? offset : 0;
00496 }
00497
00498 static int dv_read_close(AVFormatContext *s)
00499 {
00500 RawDVContext *c = s->priv_data;
00501 av_free(c->dv_demux);
00502 return 0;
00503 }
00504
00505 static int dv_probe(AVProbeData *p)
00506 {
00507 unsigned state, marker_pos = 0;
00508 int i;
00509 int matches = 0;
00510 int secondary_matches = 0;
00511
00512 if (p->buf_size < 5)
00513 return 0;
00514
00515 state = AV_RB32(p->buf);
00516 for (i = 4; i < p->buf_size; i++) {
00517 if ((state & 0xffffff7f) == 0x1f07003f)
00518 matches++;
00519
00520
00521 if ((state & 0xff07ff7f) == 0x1f07003f)
00522 secondary_matches++;
00523 if (state == 0x003f0700 || state == 0xff3f0700)
00524 marker_pos = i;
00525 if (state == 0xff3f0701 && i - marker_pos == 80)
00526 matches++;
00527 state = (state << 8) | p->buf[i];
00528 }
00529
00530 if (matches && p->buf_size / matches < 1024*1024) {
00531 if (matches > 4 || (secondary_matches >= 10 && p->buf_size / secondary_matches < 24000))
00532 return AVPROBE_SCORE_MAX*3/4;
00533 return AVPROBE_SCORE_MAX/4;
00534 }
00535 return 0;
00536 }
00537
00538 #if CONFIG_DV_DEMUXER
00539 AVInputFormat ff_dv_demuxer = {
00540 "dv",
00541 NULL_IF_CONFIG_SMALL("DV video format"),
00542 sizeof(RawDVContext),
00543 dv_probe,
00544 dv_read_header,
00545 dv_read_packet,
00546 dv_read_close,
00547 dv_read_seek,
00548 .extensions = "dv,dif",
00549 };
00550 #endif