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