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