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

📄 dv.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 3 页
字号:
            mb->partial_bit_count = 0;#ifdef VLC_DEBUG            printf("MB block: %d, %d ", mb_index, j);#endif            dv_decode_ac(&gb, mb, block);            /* write the remaining bits  in a new buffer only if the               block is finished */            if (mb->pos >= 64)                bit_copy(&pb, &gb);            block += 64;            mb++;        }        /* pass 2 : we can do it just after */#ifdef VLC_DEBUG        printf("***pass 2 size=%d MB#=%d\n", put_bits_count(&pb), mb_index);#endif        block = block1;        mb = mb1;        init_get_bits(&gb, mb_bit_buffer, put_bits_count(&pb));        flush_put_bits(&pb);        for(j = 0;j < 6; j++, block += 64, mb++) {            if (mb->pos < 64 && get_bits_left(&gb) > 0) {                dv_decode_ac(&gb, mb, block);                /* if still not finished, no need to parse other blocks */                if (mb->pos < 64)                    break;            }        }        /* all blocks are finished, so the extra bytes can be used at           the video segment level */        if (j >= 6)            bit_copy(&vs_pb, &gb);    }    /* we need a pass other the whole video segment */#ifdef VLC_DEBUG    printf("***pass 3 size=%d\n", put_bits_count(&vs_pb));#endif    block = &sblock[0][0];    mb = mb_data;    init_get_bits(&gb, vs_bit_buffer, put_bits_count(&vs_pb));    flush_put_bits(&vs_pb);    for(mb_index = 0; mb_index < 5; mb_index++) {        for(j = 0;j < 6; j++) {            if (mb->pos < 64) {#ifdef VLC_DEBUG                printf("start %d:%d\n", mb_index, j);#endif                dv_decode_ac(&gb, mb, block);            }            if (mb->pos >= 64 && mb->pos < 127)                av_log(NULL, AV_LOG_ERROR, "AC EOB marker is absent pos=%d\n", mb->pos);            block += 64;            mb++;        }    }    /* compute idct and place blocks */    block = &sblock[0][0];    mb = mb_data;    for(mb_index = 0; mb_index < 5; mb_index++) {        v = *mb_pos_ptr++;        mb_x = v & 0xff;        mb_y = v >> 8;        if (s->sys->pix_fmt == PIX_FMT_YUV422P) {            y_ptr = s->picture.data[0] + ((mb_y * s->picture.linesize[0] + (mb_x>>1))<<log2_blocksize);            c_offset = ((mb_y * s->picture.linesize[1] + (mb_x >> 2))<<log2_blocksize);        } else { /* 4:1:1 or 4:2:0 */            y_ptr = s->picture.data[0] + ((mb_y * s->picture.linesize[0] + mb_x)<<log2_blocksize);            if (s->sys->pix_fmt == PIX_FMT_YUV411P)                c_offset = ((mb_y * s->picture.linesize[1] + (mb_x >> 2))<<log2_blocksize);            else /* 4:2:0 */                c_offset = (((mb_y >> 1) * s->picture.linesize[1] + (mb_x >> 1))<<log2_blocksize);        }        for(j = 0;j < 6; j++) {            idct_put = s->idct_put[mb->dct_mode && log2_blocksize==3];            if (s->sys->pix_fmt == PIX_FMT_YUV422P) { /* 4:2:2 */                if (j == 0 || j == 2) {                    /* Y0 Y1 */                    idct_put(y_ptr + ((j >> 1)<<log2_blocksize),                             s->picture.linesize[0], block);                } else if(j > 3) {                    /* Cr Cb */                    idct_put(s->picture.data[6 - j] + c_offset,                             s->picture.linesize[6 - j], block);                }                /* note: j=1 and j=3 are "dummy" blocks in 4:2:2 */            } else { /* 4:1:1 or 4:2:0 */                if (j < 4) {                    if (s->sys->pix_fmt == PIX_FMT_YUV411P && mb_x < (704 / 8)) {                        /* NOTE: at end of line, the macroblock is handled as 420 */                        idct_put(y_ptr + (j<<log2_blocksize), s->picture.linesize[0], block);                    } else {                        idct_put(y_ptr + (((j & 1) + (j >> 1) * s->picture.linesize[0])<<log2_blocksize),                                 s->picture.linesize[0], block);                    }                } else {                    if (s->sys->pix_fmt == PIX_FMT_YUV411P && mb_x >= (704 / 8)) {                        uint64_t aligned_pixels[64/8];                        uint8_t *pixels= (uint8_t*)aligned_pixels;                        uint8_t *c_ptr, *c_ptr1, *ptr, *ptr1;                        int x, y, linesize;                        /* NOTE: at end of line, the macroblock is handled as 420 */                        idct_put(pixels, 8, block);                        linesize = s->picture.linesize[6 - j];                        c_ptr = s->picture.data[6 - j] + c_offset;                        ptr = pixels;                        for(y = 0;y < (1<<log2_blocksize); y++) {                            ptr1= ptr + (1<<(log2_blocksize-1));                            c_ptr1 = c_ptr + (linesize<<log2_blocksize);                            for(x=0; x < (1<<(log2_blocksize-1)); x++){                                c_ptr[x]= ptr[x]; c_ptr1[x]= ptr1[x];                            }                            c_ptr += linesize;                            ptr += 8;                        }                    } else {                        /* don't ask me why they inverted Cb and Cr ! */                        idct_put(s->picture.data[6 - j] + c_offset,                                 s->picture.linesize[6 - j], block);                    }                }            }            block += 64;            mb++;        }    }}#ifdef DV_CODEC_TINY_TARGET/* Converts run and level (where level != 0) pair into vlc, returning bit size */static av_always_inline int dv_rl2vlc(int run, int level, int sign, uint32_t* vlc){    int size;    if (run < DV_VLC_MAP_RUN_SIZE && level < DV_VLC_MAP_LEV_SIZE) {        *vlc = dv_vlc_map[run][level].vlc | sign;        size = dv_vlc_map[run][level].size;    }    else {        if (level < DV_VLC_MAP_LEV_SIZE) {            *vlc = dv_vlc_map[0][level].vlc | sign;            size = dv_vlc_map[0][level].size;        } else {            *vlc = 0xfe00 | (level << 1) | sign;            size = 16;        }        if (run) {            *vlc |= ((run < 16) ? dv_vlc_map[run-1][0].vlc :                                  (0x1f80 | (run - 1))) << size;            size += (run < 16) ? dv_vlc_map[run-1][0].size : 13;        }    }    return size;}static av_always_inline int dv_rl2vlc_size(int run, int level){    int size;    if (run < DV_VLC_MAP_RUN_SIZE && level < DV_VLC_MAP_LEV_SIZE) {        size = dv_vlc_map[run][level].size;    }    else {        size = (level < DV_VLC_MAP_LEV_SIZE) ? dv_vlc_map[0][level].size : 16;        if (run) {            size += (run < 16) ? dv_vlc_map[run-1][0].size : 13;        }    }    return size;}#elsestatic av_always_inline int dv_rl2vlc(int run, int l, int sign, uint32_t* vlc){    *vlc = dv_vlc_map[run][l].vlc | sign;    return dv_vlc_map[run][l].size;}static av_always_inline int dv_rl2vlc_size(int run, int l){    return dv_vlc_map[run][l].size;}#endiftypedef struct EncBlockInfo {    int area_q[4];    int bit_size[4];    int prev[5];    int cur_ac;    int cno;    int dct_mode;    DCTELEM mb[64];    uint8_t next[64];    uint8_t sign[64];    uint8_t partial_bit_count;    uint32_t partial_bit_buffer; /* we can't use uint16_t here */} EncBlockInfo;static av_always_inline PutBitContext* dv_encode_ac(EncBlockInfo* bi, PutBitContext* pb_pool,                                       PutBitContext* pb_end){    int prev;    int bits_left;    PutBitContext* pb = pb_pool;    int size = bi->partial_bit_count;    uint32_t vlc = bi->partial_bit_buffer;    bi->partial_bit_count = bi->partial_bit_buffer = 0;    for(;;){       /* Find suitable storage space */       for (; size > (bits_left = put_bits_left(pb)); pb++) {          if (bits_left) {              size -= bits_left;              put_bits(pb, bits_left, vlc >> size);              vlc = vlc & ((1<<size)-1);          }          if (pb + 1 >= pb_end) {              bi->partial_bit_count = size;              bi->partial_bit_buffer = vlc;              return pb;          }       }       /* Store VLC */       put_bits(pb, size, vlc);       if(bi->cur_ac>=64)           break;       /* Construct the next VLC */       prev= bi->cur_ac;       bi->cur_ac = bi->next[prev];       if(bi->cur_ac < 64){           size = dv_rl2vlc(bi->cur_ac - prev - 1, bi->mb[bi->cur_ac], bi->sign[bi->cur_ac], &vlc);       } else {           size = 4; vlc = 6; /* End Of Block stamp */       }    }    return pb;}static av_always_inline void dv_set_class_number(DCTELEM* blk, EncBlockInfo* bi,                                              const uint8_t* zigzag_scan, const int *weight, int bias){    int i, area;    /* We offer two different methods for class number assignment: the       method suggested in SMPTE 314M Table 22, and an improved       method. The SMPTE method is very conservative; it assigns class       3 (i.e. severe quantization) to any block where the largest AC       component is greater than 36. ffmpeg's DV encoder tracks AC bit       consumption precisely, so there is no need to bias most blocks       towards strongly lossy compression. Instead, we assign class 2       to most blocks, and use class 3 only when strictly necessary       (for blocks whose largest AC component exceeds 255). */#if 0 /* SMPTE spec method */    static const int classes[] = {12, 24, 36, 0xffff};#else /* improved ffmpeg method */    static const int classes[] = {-1, -1, 255, 0xffff};#endif    int max=classes[0];    int prev=0;    bi->mb[0] = blk[0];    for (area = 0; area < 4; area++) {       bi->prev[area] = prev;       bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :)       for (i=mb_area_start[area]; i<mb_area_start[area+1]; i++) {          int level = blk[zigzag_scan[i]];          if (level+15 > 30U) {              bi->sign[i] = (level>>31)&1;              /* weigh it and and shift down into range, adding for rounding */              /* the extra division by a factor of 2^4 reverses the 8x expansion of the DCT                 AND the 2x doubling of the weights */              level = (FFABS(level) * weight[i] + (1<<(dv_weight_bits+3))) >> (dv_weight_bits+4);              bi->mb[i] = level;              if(level>max) max= level;              bi->bit_size[area] += dv_rl2vlc_size(i - prev  - 1, level);              bi->next[prev]= i;              prev= i;          }       }    }    bi->next[prev]= i;    for(bi->cno = 0; max > classes[bi->cno]; bi->cno++);    bi->cno += bias;    if (bi->cno >= 3) {        bi->cno = 3;        prev=0;        i= bi->next[prev];        for (area = 0; area < 4; area++) {            bi->prev[area] = prev;            bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :)            for (; i<mb_area_start[area+1]; i= bi->next[i]) {                bi->mb[i] >>=1;                if (bi->mb[i]) {                    bi->bit_size[area] += dv_rl2vlc_size(i - prev - 1, bi->mb[i]);                    bi->next[prev]= i;                    prev= i;                }            }        }        bi->next[prev]= i;    }}//FIXME replace this by dsputil#define SC(x, y) ((s[x] - s[y]) ^ ((s[x] - s[y]) >> 7))static av_always_inline int dv_guess_dct_mode(DCTELEM *blk) {    DCTELEM *s;    int score88 = 0;    int score248 = 0;    int i;    /* Compute 8-8 score (small values give a better chance for 8-8 DCT) */    s = blk;    for(i=0; i<7; i++) {        score88 += SC(0,  8) + SC(1, 9) + SC(2, 10) + SC(3, 11) +                   SC(4, 12) + SC(5,13) + SC(6, 14) + SC(7, 15);        s += 8;    }    /* Compute 2-4-8 score (small values give a better chance for 2-4-8 DCT) */    s = blk;    for(i=0; i<6; i++) {        score248 += SC(0, 16) + SC(1,17) + SC(2, 18) + SC(3, 19) +                    SC(4, 20) + SC(5,21) + SC(6, 22) + SC(7, 23);        s += 8;    }    return (score88 - score248 > -10);}static inline void dv_guess_qnos(EncBlockInfo* blks, int* qnos){    int size[5];    int i, j, k, a, prev, a2;    EncBlockInfo* b;    size[0] = size[1] = size[2] = size[3] = size[4] = 1<<24;    do {       b = blks;       for (i=0; i<5; i++) {          if (!qnos[i])              continue;          qnos[i]--;          size[i] = 0;          for (j=0; j<6; j++, b++) {             for (a=0; a<4; a++) {                if (b->area_q[a] != dv_quant_shifts[qnos[i] + dv_quant_offset[b->cno]][a]) {                    b->bit_size[a] = 1; // 4 areas 4 bits for EOB :)                    b->area_q[a]++;                    prev= b->prev[a];                    assert(b->next[prev] >= mb_area_start[a+1] || b->mb[prev]);                    for (k= b->next[prev] ; k<mb_area_start[a+1]; k= b->next[k]) {                       b->mb[k] >>= 1;                       if (b->mb[k]) {                           b->bit_size[a] += dv_rl2vlc_size(k - prev - 1, b->mb[k]);                           prev= k;                       } else {                           if(b->next[k] >= mb_area_start[a+1] && b->next[k]<64){                                for(a2=a+1; b->next[k] >= mb_area_start[a2+1]; a2++)                                    b->prev[a2] = prev;                                assert(a2<4);                                assert(b->mb[b->next[k]]);                                b->bit_size[a2] += dv_rl2vlc_size(b->next[k] - prev - 1, b->mb[b->next[k]])                                                  -dv_rl2vlc_size(b->next[k] -    k - 1, b->mb[b->next[k]]);                                assert(b->prev[a2]==k && (a2+1 >= 4 || b->prev[a2+1]!=k));                                b->prev[a2] = prev;                           }                           b->next[prev] = b->next[k];                       }                    }                    b->prev[a+1]= prev;                }                size[i] += b->bit_size[a];             }          }          if(vs_total_ac_bits >= size[0] + size[1] + size[2] + size[3] + size[4])                return;       }    } while (qnos[0]|qnos[1]|qnos[2]|qnos[3]|qnos[4]);    for(a=2; a==2 || vs_total_ac_bits < size[0]; a+=a){        b = blks;        size[0] = 5*6*4; //EOB        for (j=0; j<6*5; j++, b++) {            prev= b->prev[0];            for (k= b->next[prev]; k<64; k= b->next[k]) {                if(b->mb[k] < a && b->mb[k] > -a){                    b->next[prev] = b->next[k];                }else{                    size[0] += dv_rl2vlc_size(k - prev - 1, b->mb[k]);                    prev= k;                }            }        }    }}static inline void dv_encode_video_segment(DVVideoContext *s,                                           uint8_t *dif,                                           const uint16_t *mb_pos_ptr){    int mb_index, i, j, v;    int mb_x, mb_y, c_offset, linesize;    uint8_t*  y_ptr;    uint8_t*  data;    uint8_t*  ptr;    int       do_edge_wrap;

⌨️ 快捷键说明

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