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