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