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 = CODEC_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 |= 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 = CODEC_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 = 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 c->abytes += size;
00340
00341
00342
00343 if (c->sys->height == 720) {
00344 if (buf[1] & 0x0C)
00345 c->audio_pkt[2].size = c->audio_pkt[3].size = 0;
00346 else
00347 c->audio_pkt[0].size = c->audio_pkt[1].size = 0;
00348 }
00349
00350
00351 size = dv_extract_video_info(c, buf);
00352 av_init_packet(pkt);
00353 pkt->data = buf;
00354 pkt->size = size;
00355 pkt->flags |= PKT_FLAG_KEY;
00356 pkt->stream_index = c->vst->id;
00357 pkt->pts = c->frames;
00358
00359 c->frames++;
00360
00361 return size;
00362 }
00363
00364 static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c,
00365 int64_t timestamp, int flags)
00366 {
00367
00368 const DVprofile* sys = dv_codec_profile(c->vst->codec);
00369 int64_t offset;
00370 int64_t size = url_fsize(s->pb);
00371 int64_t max_offset = ((size-1) / sys->frame_size) * sys->frame_size;
00372
00373 offset = sys->frame_size * timestamp;
00374
00375 if (offset > max_offset) offset = max_offset;
00376 else if (offset < 0) offset = 0;
00377
00378 return offset;
00379 }
00380
00381 void dv_offset_reset(DVDemuxContext *c, int64_t frame_offset)
00382 {
00383 c->frames= frame_offset;
00384 if (c->ach)
00385 c->abytes= av_rescale_q(c->frames, c->sys->time_base,
00386 (AVRational){8, c->ast[0]->codec->bit_rate});
00387 c->audio_pkt[0].size = c->audio_pkt[1].size = 0;
00388 c->audio_pkt[2].size = c->audio_pkt[3].size = 0;
00389 }
00390
00391
00392
00393
00394
00395 typedef struct RawDVContext {
00396 DVDemuxContext* dv_demux;
00397 uint8_t buf[DV_MAX_FRAME_SIZE];
00398 } RawDVContext;
00399
00400 static int dv_read_header(AVFormatContext *s,
00401 AVFormatParameters *ap)
00402 {
00403 unsigned state;
00404 RawDVContext *c = s->priv_data;
00405
00406 c->dv_demux = dv_init_demux(s);
00407 if (!c->dv_demux)
00408 return -1;
00409
00410 state = get_be32(s->pb);
00411 while ((state & 0xffffff7f) != 0x1f07003f) {
00412 if (url_feof(s->pb)) {
00413 av_log(s, AV_LOG_ERROR, "Cannot find DV header.\n");
00414 return -1;
00415 }
00416 state = (state << 8) | get_byte(s->pb);
00417 }
00418 AV_WB32(c->buf, state);
00419
00420 if (get_buffer(s->pb, c->buf + 4, DV_PROFILE_BYTES - 4) <= 0 ||
00421 url_fseek(s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0)
00422 return AVERROR(EIO);
00423
00424 c->dv_demux->sys = dv_frame_profile(c->dv_demux->sys, c->buf, DV_PROFILE_BYTES);
00425 if (!c->dv_demux->sys) {
00426 av_log(s, AV_LOG_ERROR, "Can't determine profile of DV input stream.\n");
00427 return -1;
00428 }
00429
00430 s->bit_rate = av_rescale_q(c->dv_demux->sys->frame_size, (AVRational){8,1},
00431 c->dv_demux->sys->time_base);
00432
00433 return 0;
00434 }
00435
00436
00437 static int dv_read_packet(AVFormatContext *s, AVPacket *pkt)
00438 {
00439 int size;
00440 RawDVContext *c = s->priv_data;
00441
00442 size = dv_get_packet(c->dv_demux, pkt);
00443
00444 if (size < 0) {
00445 if (!c->dv_demux->sys)
00446 return AVERROR(EIO);
00447 size = c->dv_demux->sys->frame_size;
00448 if (get_buffer(s->pb, c->buf, size) <= 0)
00449 return AVERROR(EIO);
00450
00451 size = dv_produce_packet(c->dv_demux, pkt, c->buf, size);
00452 }
00453
00454 return size;
00455 }
00456
00457 static int dv_read_seek(AVFormatContext *s, int stream_index,
00458 int64_t timestamp, int flags)
00459 {
00460 RawDVContext *r = s->priv_data;
00461 DVDemuxContext *c = r->dv_demux;
00462 int64_t offset = dv_frame_offset(s, c, timestamp, flags);
00463
00464 dv_offset_reset(c, offset / c->sys->frame_size);
00465
00466 offset = url_fseek(s->pb, offset, SEEK_SET);
00467 return (offset < 0) ? offset : 0;
00468 }
00469
00470 static int dv_read_close(AVFormatContext *s)
00471 {
00472 RawDVContext *c = s->priv_data;
00473 av_free(c->dv_demux);
00474 return 0;
00475 }
00476
00477 static int dv_probe(AVProbeData *p)
00478 {
00479 unsigned state;
00480 int i;
00481
00482 if (p->buf_size < 5)
00483 return 0;
00484
00485 state = AV_RB32(p->buf);
00486 for (i = 4; i < p->buf_size; i++) {
00487 if ((state & 0xffffff7f) == 0x1f07003f)
00488 return AVPROBE_SCORE_MAX*3/4;
00489 state = (state << 8) | p->buf[i];
00490 }
00491
00492 return 0;
00493 }
00494
00495 #if CONFIG_DV_DEMUXER
00496 AVInputFormat dv_demuxer = {
00497 "dv",
00498 NULL_IF_CONFIG_SMALL("DV video format"),
00499 sizeof(RawDVContext),
00500 dv_probe,
00501 dv_read_header,
00502 dv_read_packet,
00503 dv_read_close,
00504 dv_read_seek,
00505 .extensions = "dv,dif",
00506 };
00507 #endif