⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dv.c

📁 ffmpeg源码分析
💻 C
📖 第 1 页 / 共 3 页
字号:
    else {        buf[0] = (fr<<7) | /* FR ID 1 - first half of each channel; 0 - second */                 (0<<4)  | /* APT (Track application ID) */                 0x0f;     /* reserved -- always 1 */    }    buf[1] = 0xf0 |            /* reserved -- always 1 */             (syb_num & 0x0f); /* SSYB number 0 - 11   */    buf[2] = 0xff;             /* reserved -- always 1 */    return 3;}static void dv_format_frame(DVMuxContext *c, uint8_t* buf){    int chan, i, j, k;    for (chan = 0; chan < c->sys->n_difchan; chan++) {        for (i = 0; i < c->sys->difseg_size; i++) {            memset(buf, 0xff, 80 * 6); /* First 6 DIF blocks are for control data */            /* DV header: 1DIF */            buf += dv_write_dif_id(dv_sect_header, chan, i, 0, buf);            buf += dv_write_pack((c->sys->dsf ? dv_header625 : dv_header525), c, buf);            buf += 72; /* unused bytes */            /* DV subcode: 2DIFs */            for (j = 0; j < 2; j++) {                buf += dv_write_dif_id(dv_sect_subcode, chan, i, j, buf);                for (k = 0; k < 6; k++) {                    buf += dv_write_ssyb_id(k, (i < c->sys->difseg_size/2), buf);                    buf += dv_write_pack(dv_ssyb_packs_dist[i][k], c, buf);                }                buf += 29; /* unused bytes */            }            /* DV VAUX: 3DIFs */            for (j = 0; j < 3; j++) {                buf += dv_write_dif_id(dv_sect_vaux, chan, i, j, buf);                for (k = 0; k < 15 ; k++)                    buf += dv_write_pack(dv_vaux_packs_dist[i][k], c, buf);                buf += 2; /* unused bytes */            }            /* DV Audio/Video: 135 Video DIFs + 9 Audio DIFs */            for (j = 0; j < 135; j++) {                if (j%15 == 0) {                    memset(buf, 0xff, 80);                    buf += dv_write_dif_id(dv_sect_audio, chan, i, j/15, buf);                    buf += 77; /* audio control & shuffled PCM audio */                }                buf += dv_write_dif_id(dv_sect_video, chan, i, j, buf);                buf += 77; /* 1 video macro block: 1 bytes control                              4 * 14 bytes Y 8x8 data                              10 bytes Cr 8x8 data                              10 bytes Cb 8x8 data */            }        }    }}static void dv_inject_audio(DVMuxContext *c, const uint8_t* pcm, int channel, uint8_t* frame_ptr){    int i, j, d, of, size;    size = 4 * dv_audio_frame_size(c->sys, c->frames);    frame_ptr += channel * c->sys->difseg_size * 150 * 80;    for (i = 0; i < c->sys->difseg_size; i++) {       frame_ptr += 6 * 80; /* skip DIF segment header */       for (j = 0; j < 9; j++) {          dv_write_pack(dv_aaux_packs_dist[i][j], c, &frame_ptr[3]);          for (d = 8; d < 80; d+=2) {             of = c->sys->audio_shuffle[i][j] + (d - 8)/2 * c->sys->audio_stride;             if (of*2 >= size)                 continue;             frame_ptr[d] = pcm[of*2+1]; // FIXME: may be we have to admit             frame_ptr[d+1] = pcm[of*2]; //        that DV is a big endian PCM          }          frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */       }    }}static void dv_inject_video(DVMuxContext *c, const uint8_t* video_data, uint8_t* frame_ptr){    int chan, i, j;    int ptr = 0;    for (chan = 0; chan < c->sys->n_difchan; chan++) {        for (i = 0; i < c->sys->difseg_size; i++) {            ptr += 6 * 80; /* skip DIF segment header */            for (j = 0; j < 135; j++) {                if (j%15 == 0)                    ptr += 80; /* skip Audio DIF */                ptr += 3;                memcpy(frame_ptr + ptr, video_data + ptr, 77);                ptr += 77;            }        }    }}/* * This is the dumbest implementation of all -- it simply looks at * a fixed offset and if pack isn't there -- fails. We might want * to have a fallback mechanism for complete search of missing packs. */static const uint8_t* dv_extract_pack(uint8_t* frame, enum dv_pack_type t){    int offs;    switch (t) {    case dv_audio_source:          offs = (80*6 + 80*16*3 + 3);          break;    case dv_audio_control:          offs = (80*6 + 80*16*4 + 3);          break;    case dv_video_control:          offs = (80*5 + 48 + 5);          break;    default:          return NULL;    }    return (frame[offs] == t ? &frame[offs] : NULL);}/* * There's a couple of assumptions being made here: * 1. By default we silence erroneous (0x8000/16bit 0x800/12bit) audio samples. *    We can pass them upwards when ffmpeg will be ready to deal with them. * 2. We don't do software emphasis. * 3. Audio is always returned as 16bit linear samples: 12bit nonlinear samples *    are converted into 16bit linear ones. */static int dv_extract_audio(uint8_t* frame, uint8_t* pcm, uint8_t* pcm2,                            const DVprofile *sys){    int size, chan, i, j, d, of, smpls, freq, quant, half_ch;    uint16_t lc, rc;    const uint8_t* as_pack;    as_pack = dv_extract_pack(frame, dv_audio_source);    if (!as_pack)    /* No audio ? */        return 0;    smpls = as_pack[1] & 0x3f; /* samples in this frame - min. samples */    freq = (as_pack[4] >> 3) & 0x07; /* 0 - 48KHz, 1 - 44,1kHz, 2 - 32 kHz */    quant = as_pack[4] & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */    if (quant > 1)        return -1; /* Unsupported quantization */    size = (sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */    half_ch = sys->difseg_size/2;    /* for each DIF channel */    for (chan = 0; chan < sys->n_difchan; chan++) {        /* for each DIF segment */        for (i = 0; i < sys->difseg_size; i++) {            frame += 6 * 80; /* skip DIF segment header */            if (quant == 1 && i == half_ch) {                /* next stereo channel (12bit mode only) */                if (!pcm2)                    break;                else                    pcm = pcm2;            }            /* for each AV sequence */            for (j = 0; j < 9; j++) {                for (d = 8; d < 80; d += 2) {                    if (quant == 0) {  /* 16bit quantization */                        of = sys->audio_shuffle[i][j] + (d - 8)/2 * sys->audio_stride;                        if (of*2 >= size)                            continue;                        pcm[of*2] = frame[d+1]; // FIXME: may be we have to admit                        pcm[of*2+1] = frame[d]; //        that DV is a big endian PCM                        if (pcm[of*2+1] == 0x80 && pcm[of*2] == 0x00)                            pcm[of*2+1] = 0;                    } else {           /* 12bit quantization */                        lc = ((uint16_t)frame[d] << 4) |                             ((uint16_t)frame[d+2] >> 4);                        rc = ((uint16_t)frame[d+1] << 4) |                             ((uint16_t)frame[d+2] & 0x0f);                        lc = (lc == 0x800 ? 0 : dv_audio_12to16(lc));                        rc = (rc == 0x800 ? 0 : dv_audio_12to16(rc));                        of = sys->audio_shuffle[i%half_ch][j] + (d - 8)/3 * sys->audio_stride;                        if (of*2 >= size)                            continue;                        pcm[of*2] = lc & 0xff; // FIXME: may be we have to admit                        pcm[of*2+1] = lc >> 8; //        that DV is a big endian PCM                        of = sys->audio_shuffle[i%half_ch+half_ch][j] +                            (d - 8)/3 * sys->audio_stride;                        pcm[of*2] = rc & 0xff; // FIXME: may be we have to admit                        pcm[of*2+1] = rc >> 8; //        that DV is a big endian PCM                        ++d;                    }                }                frame += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */            }        }        /* next stereo channel (50Mbps only) */        if(!pcm2)            break;        pcm = pcm2;    }    return size;}static int dv_extract_audio_info(DVDemuxContext* c, uint8_t* frame){    const uint8_t* as_pack;    int freq, stype, smpls, quant, i, ach;    as_pack = dv_extract_pack(frame, dv_audio_source);    if (!as_pack || !c->sys) {    /* No audio ? */        c->ach = 0;        return 0;    }    smpls = as_pack[1] & 0x3f; /* samples in this frame - min. samples */    freq = (as_pack[4] >> 3) & 0x07; /* 0 - 48KHz, 1 - 44,1kHz, 2 - 32 kHz */    stype = (as_pack[3] & 0x1f); /* 0 - 2CH, 2 - 4CH */    quant = as_pack[4] & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */    /* note: ach counts PAIRS of channels (i.e. stereo channels) */    ach = (stype == 2 || (quant && (freq == 2))) ? 2 : 1;    /* Dynamic handling of the audio streams in DV */    for (i=0; i<ach; i++) {       if (!c->ast[i]) {           c->ast[i] = av_new_stream(c->fctx, 0);           if (!c->ast[i])               break;           av_set_pts_info(c->ast[i], 64, 1, 30000);           c->ast[i]->codec->codec_type = CODEC_TYPE_AUDIO;           c->ast[i]->codec->codec_id = CODEC_ID_PCM_S16LE;           av_init_packet(&c->audio_pkt[i]);           c->audio_pkt[i].size     = 0;           c->audio_pkt[i].data     = c->audio_buf[i];           c->audio_pkt[i].stream_index = c->ast[i]->index;           c->audio_pkt[i].flags |= PKT_FLAG_KEY;       }       c->ast[i]->codec->sample_rate = dv_audio_frequency[freq];       c->ast[i]->codec->channels = 2;       c->ast[i]->codec->bit_rate = 2 * dv_audio_frequency[freq] * 16;       c->ast[i]->start_time = 0;    }    c->ach = i;    return (c->sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */;}static int dv_extract_video_info(DVDemuxContext *c, uint8_t* frame){    const uint8_t* vsc_pack;    AVCodecContext* avctx;    int apt, is16_9;    int size = 0;    if (c->sys) {        avctx = c->vst->codec;        av_set_pts_info(c->vst, 64, c->sys->frame_rate_base, c->sys->frame_rate);        avctx->time_base= (AVRational){c->sys->frame_rate_base, c->sys->frame_rate};        if(!avctx->width){            avctx->width = c->sys->width;            avctx->height = c->sys->height;        }        avctx->pix_fmt = c->sys->pix_fmt;        /* finding out SAR is a little bit messy */        vsc_pack = dv_extract_pack(frame, dv_video_control);        apt = frame[4] & 0x07;        is16_9 = (vsc_pack && ((vsc_pack[2] & 0x07) == 0x02 ||                               (!apt && (vsc_pack[2] & 0x07) == 0x07)));        avctx->sample_aspect_ratio = c->sys->sar[is16_9];        avctx->bit_rate = av_rescale(c->sys->frame_size * 8,                                     c->sys->frame_rate,                                     c->sys->frame_rate_base);        size = c->sys->frame_size;    }    return size;}/* * The following 6 functions constitute our interface to the world */int dv_assemble_frame(DVMuxContext *c, AVStream* st,                      const uint8_t* data, int data_size, uint8_t** frame){    uint8_t pcm[8192];    int i;    *frame = &c->frame_buf[0];    if (c->has_audio && c->has_video &&        (c->has_audio == -1 || c->has_audio == c->n_ast)) {        /* must be a stale frame */        dv_format_frame(c, *frame);        c->frames++;        if (c->has_audio > 0)            c->has_audio = 0;        c->has_video = 0;    }    if (st->codec->codec_type == CODEC_TYPE_VIDEO) {        /* FIXME: we have to have more sensible approach than this one */        if (c->has_video)            av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames);        dv_inject_video(c, data, *frame);        c->has_video = 1;        data_size = 0;        if (c->has_audio < 0)            goto out;    }    for (i = 0; i < c->n_ast; i++) {        int reqasize, fsize;        if (st != c->ast[i])            continue;        reqasize = 4 * dv_audio_frame_size(c->sys, c->frames);        fsize = fifo_size(&c->audio_data[i], c->audio_data[i].rptr);        if (st->codec->codec_type == CODEC_TYPE_AUDIO ||            (c->has_video && fsize >= reqasize)) {            if (fsize + data_size >= reqasize && (c->has_audio < c->n_ast)) {                if (fsize >= reqasize) {                    fifo_read(&c->audio_data[i], &pcm[0], reqasize, &c->audio_data[i].rptr);                } else {                    fifo_read(&c->audio_data[i], &pcm[0], fsize, &c->audio_data[i].rptr);                    memcpy(&pcm[fsize], &data[0], reqasize - fsize);                    data += reqasize - fsize;                    data_size -= reqasize - fsize;                }                dv_inject_audio(c, &pcm[0], i, *frame);                c->has_audio += 1;            }            /* FIXME: we have to have more sensible approach than this one */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -