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 size = (sys->audio_min_samples[freq] + smpls) * 4;
00123 half_ch = sys->difseg_size / 2;
00124
00125
00126
00127 ipcm = (sys->height == 720 && !(frame[1] & 0x0C)) ? 2 : 0;
00128 pcm = ppcm[ipcm++];
00129
00130
00131 for (chan = 0; chan < sys->n_difchan; chan++) {
00132
00133 for (i = 0; i < sys->difseg_size; i++) {
00134 frame += 6 * 80;
00135 if (quant == 1 && i == half_ch) {
00136
00137 pcm = ppcm[ipcm++];
00138 if (!pcm)
00139 break;
00140 }
00141
00142
00143 for (j = 0; j < 9; j++) {
00144 for (d = 8; d < 80; d += 2) {
00145 if (quant == 0) {
00146 of = sys->audio_shuffle[i][j] + (d - 8) / 2 * sys->audio_stride;
00147 if (of*2 >= size)
00148 continue;
00149
00150 pcm[of*2] = frame[d+1];
00151 pcm[of*2+1] = frame[d];
00152 if (pcm[of*2+1] == 0x80 && pcm[of*2] == 0x00)
00153 pcm[of*2+1] = 0;
00154 } else {
00155 lc = ((uint16_t)frame[d] << 4) |
00156 ((uint16_t)frame[d+2] >> 4);
00157 rc = ((uint16_t)frame[d+1] << 4) |
00158 ((uint16_t)frame[d+2] & 0x0f);
00159 lc = (lc == 0x800 ? 0 : dv_audio_12to16(lc));
00160 rc = (rc == 0x800 ? 0 : dv_audio_12to16(rc));
00161
00162 of = sys->audio_shuffle[i%half_ch][j] + (d - 8) / 3 * sys->audio_stride;
00163 if (of*2 >= size)
00164 continue;
00165
00166 pcm[of*2] = lc & 0xff;
00167 pcm[of*2+1] = lc >> 8;
00168 of = sys->audio_shuffle[i%half_ch+half_ch][j] +
00169 (d - 8) / 3 * sys->audio_stride;
00170 pcm[of*2] = rc & 0xff;
00171 pcm[of*2+1] = rc >> 8;
00172 ++d;
00173 }
00174 }
00175
00176 frame += 16 * 80;
00177 }
00178 }
00179
00180
00181 pcm = ppcm[ipcm++];
00182 if (!pcm)
00183 break;
00184 }
00185
00186 return size;
00187 }
00188
00189 static int dv_extract_audio_info(DVDemuxContext* c, uint8_t* frame)
00190 {
00191 const uint8_t* as_pack;
00192 int freq, stype, smpls, quant, i, ach;
00193
00194 as_pack = dv_extract_pack(frame, dv_audio_source);
00195 if (!as_pack || !c->sys) {
00196 c->ach = 0;
00197 return 0;
00198 }
00199
00200 smpls = as_pack[1] & 0x3f;
00201 freq = (as_pack[4] >> 3) & 0x07;
00202 stype = (as_pack[3] & 0x1f);
00203 quant = as_pack[4] & 0x07;
00204
00205
00206 ach = ((int[4]){ 1, 0, 2, 4})[stype];
00207 if (ach == 1 && quant && freq == 2)
00208 ach = 2;
00209
00210
00211 for (i = 0; i < ach; i++) {
00212 if (!c->ast[i]) {
00213 c->ast[i] = av_new_stream(c->fctx, 0);
00214 if (!c->ast[i])
00215 break;
00216 av_set_pts_info(c->ast[i], 64, 1, 30000);
00217 c->ast[i]->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00218 c->ast[i]->codec->codec_id = CODEC_ID_PCM_S16LE;
00219
00220 av_init_packet(&c->audio_pkt[i]);
00221 c->audio_pkt[i].size = 0;
00222 c->audio_pkt[i].data = c->audio_buf[i];
00223 c->audio_pkt[i].stream_index = c->ast[i]->index;
00224 c->audio_pkt[i].flags |= AV_PKT_FLAG_KEY;
00225 }
00226 c->ast[i]->codec->sample_rate = dv_audio_frequency[freq];
00227 c->ast[i]->codec->channels = 2;
00228 c->ast[i]->codec->bit_rate = 2 * dv_audio_frequency[freq] * 16;
00229 c->ast[i]->start_time = 0;
00230 }
00231 c->ach = i;
00232
00233 return (c->sys->audio_min_samples[freq] + smpls) * 4; ;
00234 }
00235
00236 static int dv_extract_video_info(DVDemuxContext *c, uint8_t* frame)
00237 {
00238 const uint8_t* vsc_pack;
00239 AVCodecContext* avctx;
00240 int apt, is16_9;
00241 int size = 0;
00242
00243 if (c->sys) {
00244 avctx = c->vst->codec;
00245
00246 av_set_pts_info(c->vst, 64, c->sys->time_base.num,
00247 c->sys->time_base.den);
00248 avctx->time_base= c->sys->time_base;
00249 if (!avctx->width){
00250 avctx->width = c->sys->width;
00251 avctx->height = c->sys->height;
00252 }
00253 avctx->pix_fmt = c->sys->pix_fmt;
00254
00255
00256 vsc_pack = dv_extract_pack(frame, dv_video_control);
00257 apt = frame[4] & 0x07;
00258 is16_9 = (vsc_pack && ((vsc_pack[2] & 0x07) == 0x02 ||
00259 (!apt && (vsc_pack[2] & 0x07) == 0x07)));
00260 c->vst->sample_aspect_ratio = c->sys->sar[is16_9];
00261 avctx->bit_rate = av_rescale_q(c->sys->frame_size, (AVRational){8,1},
00262 c->sys->time_base);
00263 size = c->sys->frame_size;
00264 }
00265 return size;
00266 }
00267
00268
00269
00270
00271
00272 DVDemuxContext* dv_init_demux(AVFormatContext *s)
00273 {
00274 DVDemuxContext *c;
00275
00276 c = av_mallocz(sizeof(DVDemuxContext));
00277 if (!c)
00278 return NULL;
00279
00280 c->vst = av_new_stream(s, 0);
00281 if (!c->vst) {
00282 av_free(c);
00283 return NULL;
00284 }
00285
00286 c->sys = NULL;
00287 c->fctx = s;
00288 memset(c->ast, 0, sizeof(c->ast));
00289 c->ach = 0;
00290 c->frames = 0;
00291 c->abytes = 0;
00292
00293 c->vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00294 c->vst->codec->codec_id = CODEC_ID_DVVIDEO;
00295 c->vst->codec->bit_rate = 25000000;
00296 c->vst->start_time = 0;
00297
00298 return c;
00299 }
00300
00301 int dv_get_packet(DVDemuxContext *c, AVPacket *pkt)
00302 {
00303 int size = -1;
00304 int i;
00305
00306 for (i = 0; i < c->ach; i++) {
00307 if (c->ast[i] && c->audio_pkt[i].size) {
00308 *pkt = c->audio_pkt[i];
00309 c->audio_pkt[i].size = 0;
00310 size = pkt->size;
00311 break;
00312 }
00313 }
00314
00315 return size;
00316 }
00317
00318 int dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,
00319 uint8_t* buf, int buf_size)
00320 {
00321 int size, i;
00322 uint8_t *ppcm[4] = {0};
00323
00324 if (buf_size < DV_PROFILE_BYTES ||
00325 !(c->sys = ff_dv_frame_profile(c->sys, buf, buf_size)) ||
00326 buf_size < c->sys->frame_size) {
00327 return -1;
00328 }
00329
00330
00331
00332 size = dv_extract_audio_info(c, buf);
00333 for (i = 0; i < c->ach; i++) {
00334 c->audio_pkt[i].size = size;
00335 c->audio_pkt[i].pts = c->abytes * 30000*8 / c->ast[i]->codec->bit_rate;
00336 ppcm[i] = c->audio_buf[i];
00337 }
00338 dv_extract_audio(buf, ppcm, c->sys);
00339
00340
00341
00342 if (c->sys->height == 720) {
00343 if (buf[1] & 0x0C) {
00344 c->audio_pkt[2].size = c->audio_pkt[3].size = 0;
00345 } else {
00346 c->audio_pkt[0].size = c->audio_pkt[1].size = 0;
00347 c->abytes += size;
00348 }
00349 } else {
00350 c->abytes += size;
00351 }
00352
00353
00354 size = dv_extract_video_info(c, buf);
00355 av_init_packet(pkt);
00356 pkt->data = buf;
00357 pkt->size = size;
00358 pkt->flags |= AV_PKT_FLAG_KEY;
00359 pkt->stream_index = c->vst->id;
00360 pkt->pts = c->frames;
00361
00362 c->frames++;
00363
00364 return size;
00365 }
00366
00367 static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c,
00368 int64_t timestamp, int flags)
00369 {
00370
00371 const DVprofile* sys = ff_dv_codec_profile(c->vst->codec);
00372 int64_t offset;
00373 int64_t size = url_fsize(s->pb);
00374 int64_t max_offset = ((size-1) / sys->frame_size) * sys->frame_size;
00375
00376 offset = sys->frame_size * timestamp;
00377
00378 if (size >= 0 && offset > max_offset) offset = max_offset;
00379 else if (offset < 0) offset = 0;
00380
00381 return offset;
00382 }
00383
00384 void dv_offset_reset(DVDemuxContext *c, int64_t frame_offset)
00385 {
00386 c->frames= frame_offset;
00387 if (c->ach)
00388 c->abytes= av_rescale_q(c->frames, c->sys->time_base,
00389 (AVRational){8, c->ast[0]->codec->bit_rate});
00390 c->audio_pkt[0].size = c->audio_pkt[1].size = 0;
00391 c->audio_pkt[2].size = c->audio_pkt[3].size = 0;
00392 }
00393
00394
00395
00396
00397
00398 typedef struct RawDVContext {
00399 DVDemuxContext* dv_demux;
00400 uint8_t buf[DV_MAX_FRAME_SIZE];
00401 } RawDVContext;
00402
00403 static int dv_read_header(AVFormatContext *s,
00404 AVFormatParameters *ap)
00405 {
00406 unsigned state, marker_pos = 0;
00407 RawDVContext *c = s->priv_data;
00408
00409 c->dv_demux = dv_init_demux(s);
00410 if (!c->dv_demux)
00411 return -1;
00412
00413 state = get_be32(s->pb);
00414 while ((state & 0xffffff7f) != 0x1f07003f) {
00415 if (url_feof(s->pb)) {
00416 av_log(s, AV_LOG_ERROR, "Cannot find DV header.\n");
00417 return -1;
00418 }
00419 if (state == 0x003f0700 || state == 0xff3f0700)
00420 marker_pos = url_ftell(s->pb);
00421 if (state == 0xff3f0701 && url_ftell(s->pb) - marker_pos == 80) {
00422 url_fseek(s->pb, -163, SEEK_CUR);
00423 state = get_be32(s->pb);
00424 break;
00425 }
00426 state = (state << 8) | get_byte(s->pb);
00427 }
00428 AV_WB32(c->buf, state);
00429
00430 if (get_buffer(s->pb, c->buf + 4, DV_PROFILE_BYTES - 4) <= 0 ||
00431 url_fseek(s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0)
00432 return AVERROR(EIO);
00433
00434 c->dv_demux->sys = ff_dv_frame_profile(c->dv_demux->sys, c->buf, DV_PROFILE_BYTES);
00435 if (!c->dv_demux->sys) {
00436 av_log(s, AV_LOG_ERROR, "Can't determine profile of DV input stream.\n");
00437 return -1;
00438 }
00439
00440 s->bit_rate = av_rescale_q(c->dv_demux->sys->frame_size, (AVRational){8,1},
00441 c->dv_demux->sys->time_base);
00442
00443 return 0;
00444 }
00445
00446
00447 static int dv_read_packet(AVFormatContext *s, AVPacket *pkt)
00448 {
00449 int size;
00450 RawDVContext *c = s->priv_data;
00451
00452 size = dv_get_packet(c->dv_demux, pkt);
00453
00454 if (size < 0) {
00455 if (!c->dv_demux->sys)
00456 return AVERROR(EIO);
00457 size = c->dv_demux->sys->frame_size;
00458 if (get_buffer(s->pb, c->buf, size) <= 0)
00459 return AVERROR(EIO);
00460
00461 size = dv_produce_packet(c->dv_demux, pkt, c->buf, size);
00462 }
00463
00464 return size;
00465 }
00466
00467 static int dv_read_seek(AVFormatContext *s, int stream_index,
00468 int64_t timestamp, int flags)
00469 {
00470 RawDVContext *r = s->priv_data;
00471 DVDemuxContext *c = r->dv_demux;
00472 int64_t offset = dv_frame_offset(s, c, timestamp, flags);
00473
00474 dv_offset_reset(c, offset / c->sys->frame_size);
00475
00476 offset = url_fseek(s->pb, offset, SEEK_SET);
00477 return (offset < 0) ? offset : 0;
00478 }
00479
00480 static int dv_read_close(AVFormatContext *s)
00481 {
00482 RawDVContext *c = s->priv_data;
00483 av_free(c->dv_demux);
00484 return 0;
00485 }
00486
00487 static int dv_probe(AVProbeData *p)
00488 {
00489 unsigned state, marker_pos = 0;
00490 int i;
00491 int matches = 0;
00492 int secondary_matches = 0;
00493
00494 if (p->buf_size < 5)
00495 return 0;
00496
00497 state = AV_RB32(p->buf);
00498 for (i = 4; i < p->buf_size; i++) {
00499 if ((state & 0xffffff7f) == 0x1f07003f)
00500 matches++;
00501
00502
00503 if ((state & 0xff07ff7f) == 0x1f07003f)
00504 secondary_matches++;
00505 if (state == 0x003f0700 || state == 0xff3f0700)
00506 marker_pos = i;
00507 if (state == 0xff3f0701 && i - marker_pos == 80)
00508 matches++;
00509 state = (state << 8) | p->buf[i];
00510 }
00511
00512 if (matches && p->buf_size / matches < 1024*1024) {
00513 if (matches > 4 || (secondary_matches >= 10 && p->buf_size / secondary_matches < 24000))
00514 return AVPROBE_SCORE_MAX*3/4;
00515 return AVPROBE_SCORE_MAX/4;
00516 }
00517 return 0;
00518 }
00519
00520 #if CONFIG_DV_DEMUXER
00521 AVInputFormat dv_demuxer = {
00522 "dv",
00523 NULL_IF_CONFIG_SMALL("DV video format"),
00524 sizeof(RawDVContext),
00525 dv_probe,
00526 dv_read_header,
00527 dv_read_packet,
00528 dv_read_close,
00529 dv_read_seek,
00530 .extensions = "dv,dif",
00531 };
00532 #endif