Index: libavcodec/dv.c =================================================================== --- libavcodec/dv.c (revision 11056) +++ libavcodec/dv.c (working copy) @@ -6,8 +6,9 @@ * DV encoder * Copyright (c) 2003 Roman Shaposhnik. * - * 50 Mbps (DVCPRO50) support - * Copyright (c) 2006 Daniel Maas + * 50 Mbps (DVCPRO50) and 100 Mbps (DVCPRO HD) support + * Copyright (c) 2006 Maas Digital LLC (Dan Maas, ) + * Funded by BBC Research & Development * * Many thanks to Dan Dennedy for providing wealth * of DV technical info. @@ -59,8 +60,8 @@ /* MultiThreading - dv_anchor applies to entire DV codec, not just the avcontext */ /* one element is needed for each video segment in a DV frame */ -/* at most there are 2 DIF channels * 12 DIF sequences * 27 video segments (PAL 50Mbps) */ -#define DV_ANCHOR_SIZE (2*12*27) +/* at most there are 4 DIF channels * 12 DIF sequences * 27 video segments (1080i50) */ +#define DV_ANCHOR_SIZE (4*12*27) static void* dv_anchor[DV_ANCHOR_SIZE]; @@ -71,16 +72,14 @@ #define DV_VLC_MAP_LEV_SIZE 23 #else #define DV_VLC_MAP_RUN_SIZE 64 -#define DV_VLC_MAP_LEV_SIZE 512 //FIXME sign was removed so this should be /2 but needs check +#define DV_VLC_MAP_LEV_SIZE 256 #endif /* XXX: also include quantization */ -static RL_VLC_ELEM dv_rl_vlc[1184]; +static RL_VLC_ELEM *dv_rl_vlc; /* VLC encoding lookup table */ -static struct dv_vlc_pair { - uint32_t vlc; - uint8_t size; -} dv_vlc_map[DV_VLC_MAP_RUN_SIZE][DV_VLC_MAP_LEV_SIZE]; +static uint32_t (*dv_vlc_map_vlc)[DV_VLC_MAP_LEV_SIZE] = NULL; +static uint8_t (*dv_vlc_map_size)[DV_VLC_MAP_LEV_SIZE] = NULL; static void dv_build_unquantize_tables(DVVideoContext *s, uint8_t* perm) { @@ -123,6 +122,13 @@ done = 1; + dv_vlc_map_vlc = av_mallocz_static(DV_VLC_MAP_LEV_SIZE*DV_VLC_MAP_RUN_SIZE*sizeof(uint32_t)); + if (!dv_vlc_map_vlc) + return -ENOMEM; + dv_vlc_map_size = av_mallocz_static(DV_VLC_MAP_LEV_SIZE*DV_VLC_MAP_RUN_SIZE*sizeof(uint8_t)); + if (!dv_vlc_map_size) + return -ENOMEM; + /* dv_anchor lets each thread know its Id */ for (i=0; iscan_table; @@ -336,10 +342,15 @@ break; pos1 = scan_table[pos]; - level <<= shift_table[pos1]; - /* unweigh, round, and shift down */ - level = (level*iweight_table[pos] + (1 << (dv_iweight_bits-1))) >> dv_iweight_bits; + /* unweigh, round, and shift down */ + if (DV_PROFILE_IS_HD(s->sys)) { + level *= mb->qstep; + level = (level*iweight_table[pos]) >> 5; + } else { + level <<= shift_table[pos1]; + level = (level*iweight_table[pos] + (1 << (dv_iweight_bits-1))) >> dv_iweight_bits; + } block[pos1] = level; @@ -361,13 +372,79 @@ } } +/* interleave scanlines from even- and odd-numbered blocks */ +static void dv100_interleave(DVVideoContext *s, int mb_x, int mb_y, uint8_t *y_ptr, int c_offset) +{ + int i; + for (i = 0; i < 4; i++) { + uint8_t *p0, *p1; /* pointer to first scanline of the two adjacent blocks */ + int stride; /* offset between successive scanlines */ + + /* duplicated code */ + if (i < 2) { /* DCT0/DCT2, DCT1/DCT3 */ + if (s->sys->height == 1080 && mb_y == 134) { + /* bottom edge: horizontal row of 4 blocks */ + p0 = y_ptr + ((i+0)<<3); + p1 = y_ptr + ((i+2)<<3); + } else { + p0 = y_ptr + ((((i+0) & 1) + ((i+0) >> 1) * s->picture.linesize[0])<<3); + p1 = y_ptr + ((((i+2) & 1) + ((i+2) >> 1) * s->picture.linesize[0])<<3); + } + stride = s->picture.linesize[0]; + } else { /* DCT4/DCT5, DCT6/DCT7 */ + int j = i<<1; + int chan = 2 - ((j-4)>>1); + if (s->sys->height == 1080 && mb_y == 134) { + /* bottom edge: horizontal row of 2 blocks */ + p0 = s->picture.data[chan] + c_offset + (((j+0)&1)<<3); + p1 = s->picture.data[chan] + c_offset + (((j+1)&1)<<3); + } else { + p0 = s->picture.data[chan] + c_offset + ((((j+0) & 1) * s->picture.linesize[chan])<<3); + p1 = s->picture.data[chan] + c_offset + ((((j+1) & 1) * s->picture.linesize[chan])<<3); + } + stride = s->picture.linesize[chan]; + } + + /* GCC turns these small fixed-size memcpy()s into efficient mov sequences */ +#define SET(a,b) memcpy(a, b, 8); + { + uint8_t temp[7][8]; + + SET(temp[0], p0+1*stride); + SET(temp[1], p0+2*stride); + SET(temp[2], p0+3*stride); + SET(temp[3], p0+4*stride); + SET(temp[4], p0+5*stride); + SET(temp[5], p0+6*stride); + SET(temp[6], p0+7*stride); + + SET(p0+1*stride, p1+0*stride); + SET(p0+2*stride, temp[0]); + SET(p0+3*stride, p1+1*stride); + SET(p0+4*stride, temp[1]); + SET(p0+5*stride, p1+2*stride); + SET(p0+6*stride, temp[2]); + SET(p0+7*stride, p1+3*stride); + + SET(p1+0*stride, temp[3]); + SET(p1+1*stride, p1+4*stride); + SET(p1+2*stride, temp[4]); + SET(p1+3*stride, p1+5*stride); + SET(p1+4*stride, temp[5]); + SET(p1+5*stride, p1+6*stride); + SET(p1+6*stride, temp[6]); + } +#undef SET + } +} + /* mb_x and mb_y are in units of 8 pixels */ static inline void dv_decode_video_segment(DVVideoContext *s, uint8_t *buf_ptr1, - const uint16_t *mb_pos_ptr) + const int mb_pos_ptr[10]) { int quant, dc, dct_mode, class1, j; - int mb_index, mb_x, mb_y, v, last_index; + int mb_index, mb_x, mb_y, last_index; DCTELEM *block, *block1; int c_offset; uint8_t *y_ptr; @@ -375,14 +452,15 @@ uint8_t *buf_ptr; PutBitContext pb, vs_pb; GetBitContext gb; - BlockInfo mb_data[5 * 6], *mb, *mb1; - DECLARE_ALIGNED_8(DCTELEM, sblock[5*6][64]); + BlockInfo mb_data[5 * DV_MAX_BPM], *mb, *mb1; + DECLARE_ALIGNED_8(DCTELEM, sblock[5*DV_MAX_BPM][64]); DECLARE_ALIGNED_8(uint8_t, mb_bit_buffer[80 + 4]); /* allow some slack */ DECLARE_ALIGNED_8(uint8_t, vs_bit_buffer[5 * 80 + 4]); /* allow some slack */ const int log2_blocksize= 3-s->avctx->lowres; + int dv100_dct_mode[5]; /* dct_mode is per-macroblock in DV100, not per-block */ - assert((((int)mb_bit_buffer)&7)==0); - assert((((int)vs_bit_buffer)&7)==0); + assert((((long)mb_bit_buffer)&7)==0); + assert((((long)vs_bit_buffer)&7)==0); memset(sblock, 0, sizeof(sblock)); @@ -391,26 +469,49 @@ block1 = &sblock[0][0]; mb1 = mb_data; init_put_bits(&vs_pb, vs_bit_buffer, 5 * 80); - for(mb_index = 0; mb_index < 5; mb_index++, mb1 += 6, block1 += 6 * 64) { + for(mb_index = 0; mb_index < 5; mb_index++, mb1 += s->sys->bpm, block1 += s->sys->bpm * 64) { /* skip header */ quant = buf_ptr[3] & 0x0f; buf_ptr += 4; init_put_bits(&pb, mb_bit_buffer, 80); mb = mb1; block = block1; - for(j = 0;j < 6; j++) { - last_index = block_sizes[j]; + for(j = 0;j < s->sys->bpm; j++) { + last_index = s->sys->block_sizes[j]; init_get_bits(&gb, buf_ptr, last_index); /* get the dc */ dc = get_sbits(&gb, 9); dct_mode = get_bits1(&gb); - mb->dct_mode = dct_mode; - mb->scan_table = s->dv_zigzag[dct_mode]; - mb->iweight_table = dct_mode ? dv_iweight_248 : dv_iweight_88; class1 = get_bits(&gb, 2); - mb->shift_table = s->dv_idct_shift[class1 == 3][dct_mode] - [quant + dv_quant_offset[class1]]; + + if (DV_PROFILE_IS_HD(s->sys)) { + if (j == 0) { + /* macroblock Y location */ + int mb_y = mb_pos_ptr[2*mb_index+1]; + /* force non-field mode for 4x1 "bottom macro blocks" */ + if(mb_y == 134) { + dv100_dct_mode[mb_index] = 0; + } else { + dv100_dct_mode[mb_index] = dct_mode; + } + } + /* DV100 does not use the 2-4-8 DCT */ + mb->dct_mode = 0; + if (s->sys->height == 1080) { + mb->iweight_table = (j < 4) ? dv_iweight_1080_y : dv_iweight_1080_c; + } else { /* 720p */ + mb->iweight_table = (j < 4) ? dv_iweight_720_y : dv_iweight_720_c; + } + mb->qstep = dv100_qstep[quant] << class1; + } else { + mb->dct_mode = dct_mode; + mb->iweight_table = dct_mode ? dv_iweight_248 : dv_iweight_88; + mb->shift_table = s->dv_idct_shift[class1 == 3][dct_mode] + [quant + dv_quant_offset[class1]]; + } + mb->scan_table = s->dv_zigzag[mb->dct_mode]; + dc = dc << 2; /* convert to unsigned because 128 is not added in the standard IDCT */ @@ -423,7 +524,7 @@ #ifdef VLC_DEBUG printf("MB block: %d, %d ", mb_index, j); #endif - dv_decode_ac(&gb, mb, block); + dv_decode_ac(s, &gb, mb, block); /* write the remaining bits in a new buffer only if the block is finished */ @@ -442,9 +543,9 @@ 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++) { + for(j = 0;j < s->sys->bpm; j++, block += 64, mb++) { if (mb->pos < 64 && get_bits_left(&gb) > 0) { - dv_decode_ac(&gb, mb, block); + dv_decode_ac(s, &gb, mb, block); /* if still not finished, no need to parse other blocks */ if (mb->pos < 64) break; @@ -452,7 +553,7 @@ } /* all blocks are finished, so the extra bytes can be used at the video segment level */ - if (j >= 6) + if (j >= s->sys->bpm) bit_copy(&vs_pb, &gb); } @@ -465,12 +566,12 @@ 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++) { + for(j = 0;j < s->sys->bpm; j++) { if (mb->pos < 64) { #ifdef VLC_DEBUG printf("start %d:%d\n", mb_index, j); #endif - dv_decode_ac(&gb, mb, block); + dv_decode_ac(s, &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); @@ -483,10 +584,9 @@ 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) { + mb_x = *mb_pos_ptr++; + mb_y = *mb_pos_ptr++; + if (s->sys->pix_fmt == PIX_FMT_YUV422P) { /* 4:2:2 */ y_ptr = s->picture.data[0] + ((mb_y * s->picture.linesize[0] + (mb_x>>1))<picture.linesize[1] + (mb_x >> 2))<> 1) * s->picture.linesize[1] + (mb_x >> 1))<sys->bpm; j++) { idct_put = s->idct_put[mb->dct_mode && log2_blocksize==3]; - if (s->sys->pix_fmt == PIX_FMT_YUV422P) { /* 4:2:2 */ + if (DV_PROFILE_IS_HD(s->sys)) { /* HD 4:2:2 */ + if (j < 4) { /* Four Y blocks */ + /* NOTE: at bottom of image in 1080i50/60, the macroblock is handled as 411 */ + if (s->sys->height == 1080 && mb_y == 134) { + idct_put(y_ptr + (j<picture.linesize[0], block); + } else { + idct_put(y_ptr + (((j & 1) + (j >> 1) * s->picture.linesize[0])<picture.linesize[0], block); + } + } else { /* Cr and Cb blocks */ + int chan = 2 - ((j-4)>>1); + if (s->sys->height == 1080 && mb_y == 134) { + /* bottom edge: horizontal row of 2 blocks */ + idct_put(s->picture.data[chan] + c_offset + ((j&1)<picture.linesize[chan], block); + } else { + idct_put(s->picture.data[chan] + c_offset + (((j & 1) * s->picture.linesize[chan])<picture.linesize[chan], block); + } + } + } else if (s->sys->pix_fmt == PIX_FMT_YUV422P) { /* SD 4:2:2 */ if (j == 0 || j == 2) { /* Y0 Y1 */ idct_put(y_ptr + ((j >> 1)<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 */ + /* note: j=1 and j=3 are "dummy" blocks in SD 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)) { @@ -548,6 +668,9 @@ block += 64; mb++; } + if (DV_PROFILE_IS_HD(s->sys) && dv100_dct_mode[mb_index]) { + dv100_interleave(s, mb_x, mb_y, y_ptr, c_offset); + } } } @@ -557,21 +680,21 @@ { 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; + *vlc = dv_vlc_map_vlc[run][level] | sign; + size = dv_vlc_map_size[run][level]; } else { if (level < DV_VLC_MAP_LEV_SIZE) { - *vlc = dv_vlc_map[0][level].vlc | sign; - size = dv_vlc_map[0][level].size; + *vlc = dv_vlc_map_vlc[0][level] | sign; + size = dv_vlc_map_size[0][level]; } else { *vlc = 0xfe00 | (level << 1) | sign; size = 16; } if (run) { - *vlc |= ((run < 16) ? dv_vlc_map[run-1][0].vlc : + *vlc |= ((run < 16) ? dv_vlc_map_vlc[run-1][0] : (0x1f80 | (run - 1))) << size; - size += (run < 16) ? dv_vlc_map[run-1][0].size : 13; + size += (run < 16) ? dv_vlc_map_size[run-1][0] : 13; } } @@ -583,12 +706,12 @@ int size; if (run < DV_VLC_MAP_RUN_SIZE && level < DV_VLC_MAP_LEV_SIZE) { - size = dv_vlc_map[run][level].size; + size = dv_vlc_map_size[run][level]; } else { - size = (level < DV_VLC_MAP_LEV_SIZE) ? dv_vlc_map[0][level].size : 16; + size = (level < DV_VLC_MAP_LEV_SIZE) ? dv_vlc_map_size[0][level] : 16; if (run) { - size += (run < 16) ? dv_vlc_map[run-1][0].size : 13; + size += (run < 16) ? dv_vlc_map_size[run-1][0] : 13; } } return size; @@ -596,24 +719,29 @@ #else static 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; + *vlc = dv_vlc_map_vlc[run][l] | sign; + return dv_vlc_map_size[run][l]; } static av_always_inline int dv_rl2vlc_size(int run, int l) { - return dv_vlc_map[run][l].size; + return dv_vlc_map_size[run][l]; } #endif typedef struct EncBlockInfo { int area_q[4]; int bit_size[4]; - int prev[5]; + int prev[5]; /* first nonzero component before each area start (not used in DV100) */ int cur_ac; int cno; + int min_qlevel; /* DV100 only: minimum qlevel (for AC coefficients >255) */ int dct_mode; DCTELEM mb[64]; + /* used by DV100 only: a copy of the weighted and classified but + not-yet-quantized AC coefficients. this is necessary for + re-quantizing at different steps. */ + DCTELEM save[64]; uint8_t next[64]; uint8_t sign[64]; uint8_t partial_bit_count; @@ -663,8 +791,8 @@ 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) +static inline void dv_set_class_number_sd(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 @@ -733,6 +861,133 @@ } } +/* After quantization, set the class number by looking at the largest + AC component. Increase the class number until it fits in 8 bits. */ +static inline void dv100_set_cno(EncBlockInfo *bi, int max, int bias) +{ + int prev, i; + int delta = 0; + + /* starting cno */ + bi->cno = bias; + + /* bump the class number up if the maximum AC coefficient is too + large for 8 bits */ + while ((max & ~(0xFF)) && (bi->cno < 3)) { + bi->cno++; + delta++; + max >>= 1; + } + + /* if cno stays the same, we are done */ + if(delta == 0) { + return; + } + + /* divide AC components by 2^(delta), re-building the run-length table and + updating bit_size as we go */ + bi->bit_size[0] = 4; /* EOB code is 4 bits */ + + /* skip through the run-length table, visiting all nonzero components */ + prev = 0; + + /* visit nonzero components and rescale them */ + for (i = bi->next[prev]; i < 64; i = bi->next[i]) { + bi->mb[i] >>= delta; + + /* clamp to max amplitude */ + /* (yes, it is possible to hit this even when cno=3!) */ + if (bi->mb[i] > 255) + bi->mb[i] = 255; + + /* maintain run-length table */ + if (bi->mb[i]) { + bi->bit_size[0] += dv_rl2vlc_size(i - prev - 1, bi->mb[i]); + prev = i; + } else { + bi->next[prev] = bi->next[i]; + } + } + /* mark EOB */ + bi->next[prev] = i; +} + +/* DV100 quantize + Perform quantization by divinding the AC component by the qstep. + As an optimization we use a fixed-point integer multiply instead + of a divide. */ +static av_always_inline int dv100_quantize(int level, int qsinv) +{ + /* this code is equivalent to */ + /* return (level + qs/2) / qs; */ + + return (level * qsinv + 1024 + (1<<(dv100_qstep_bits-1))) >> dv100_qstep_bits; + + /* the extra +1024 is needed to make the rounding come out right. */ + + /* I (DJM) have verified that the results are exactly the same as + division for level 0-2048 at all QNOs. */ +} + +/* this function just copies the DCT coefficients and performs + the initial (non-)quantization. */ +static inline void dv_set_class_number_hd(DCTELEM* blk, EncBlockInfo* bi, + const uint8_t* zigzag_scan, const int *weight, int bias) +{ + int i, max = 0; + + /* the first quantization (none at all) */ + bi->area_q[0] = 1; + + /* LOOP1: weigh AC components and store to save[] */ + /* (i=0 is the DC component; we only include it to make the + number of loop iterations even, for future possible SIMD optimization) */ + for (i = 0; i < 64; i += 2) { + int level0, level1; + + /* get the AC component (in zig-zag order) */ + level0 = blk[zigzag_scan[i+0]]; + level1 = blk[zigzag_scan[i+1]]; + + /* extract sign and make it the lowest bit */ + bi->sign[i+0] = (level0>>31)&1; + bi->sign[i+1] = (level1>>31)&1; + + /* take absolute value of the level */ + level0 = FFABS(level0); + level1 = FFABS(level1); + + /* weigh it */ + level0 = (level0*weight[i+0] + 4096 + (1<<17)) >> 18; + level1 = (level1*weight[i+1] + 4096 + (1<<17)) >> 18; + + /* save unquantized value */ + bi->save[i+0] = level0; + bi->save[i+1] = level1; + } + + /* find max component */ + for (i = 0; i < 64; i++) { + int ac = bi->save[i]; + if (ac > max) + max = ac; + } + + /* copy DC component */ + bi->mb[0] = blk[0]; + + /* the EOB code is 4 bits */ + bi->bit_size[0] = 4; + bi->bit_size[1] = bi->bit_size[2] = bi->bit_size[3] = 0; + + /* ensure that no AC coefficients are cut off */ + bi->min_qlevel = ((max+256) >> 8); + + bi->area_q[0] = 25; /* set to an "impossible" value */ + bi->cno = 0; +} + + //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) { @@ -759,7 +1014,7 @@ return (score88 - score248 > -10); } -static inline void dv_guess_qnos(EncBlockInfo* blks, int* qnos) +static inline void dv_guess_qnos_sd(EncBlockInfo* blks, int* qnos, int vs_total_ac_bits) { int size[5]; int i, j, k, a, prev, a2; @@ -828,19 +1083,235 @@ } } +static int dv100_actual_quantize(EncBlockInfo *b, int qlevel) +{ + int prev, k, qsinv; + + int qno = DV100_QLEVEL_QNO(dv100_qlevels[qlevel]); + int cno = DV100_QLEVEL_CNO(dv100_qlevels[qlevel]); + + if(b->area_q[0] == qno && b->cno == cno) + return b->bit_size[0]; + + qsinv = dv100_qstep_inv[qno]; + + /* record the new qstep */ + b->area_q[0] = qno; + b->cno = cno; + + /* reset encoded size (EOB = 4 bits) */ + b->bit_size[0] = 4; + + /* visit nonzero components and quantize */ + prev = 0; + for (k = 1; k < 64; k++) { + /* quantize */ + int ac = dv100_quantize(b->save[k], qsinv) >> cno; + if(ac) { + if(ac > 255) + ac = 255; + + b->mb[k] = ac; + b->bit_size[0] += dv_rl2vlc_size(k - prev - 1, ac); + b->next[prev] = k; + prev = k; + } + } + b->next[prev] = k; + + return b->bit_size[0]; +} + +static inline void dv_guess_qnos_hd(EncBlockInfo *blks, int* qnos, int vs_total_ac_bits, int qno_memory[5]) +{ + EncBlockInfo *b; + int min_qlevel[5]; + int qlevels[5]; + int size[5]; + int i, j; + + static const int enable_finer = 1; + + /* cache block sizes at hypothetical qlevels */ + uint16_t size_cache[5*8][dv100_num_qlevels]; + + memset(size_cache, 0, sizeof(size_cache)); + + /* get minimum qlevels */ + for (i = 0; i < 5; i++) { + min_qlevel[i] = 1; + for (j = 0; j < 8; j++) { + if (blks[8*i+j].min_qlevel > min_qlevel[i]) + min_qlevel[i] = blks[8*i+j].min_qlevel; + } + } + + /* initialize sizes */ + for (i = 0; i < 5; i++) { + qlevels[i] = qno_memory[i]; + if (qlevels[i] < min_qlevel[i]) + qlevels[i] = min_qlevel[i]; + + qnos[i] = DV100_QLEVEL_QNO(dv100_qlevels[qlevels[i]]); + size[i] = 0; + for (j = 0; j < 8; j++) { + size_cache[8*i+j][qlevels[i]] = dv100_actual_quantize(&blks[8*i+j], qlevels[i]); + size[i] += size_cache[8*i+j][qlevels[i]]; + } + } + + /* must we go coarser? */ + if((size[0]+size[1]+size[2]+size[3]+size[4]) > vs_total_ac_bits) { + + int largest = (size[0] % 5); /* 'random' number */ + + do { + /* find the macroblock with the lowest qlevel */ + for (i = 0; i < 5; i++) { + if ((qlevels[i] < (dv100_num_qlevels-1)) && + (qlevels[i] < qlevels[largest])) + largest = i; + } + + i = largest; + + /* ensure that we don't enter infinite loop */ + largest = (largest+1) % 5; + + if (qlevels[i] >= (dv100_num_qlevels-1)) { + /* can't quantize any more */ + continue; + } + + /* quantize a little bit more */ + qlevels[i] += dv100_qlevel_inc; + if (qlevels[i] > (dv100_num_qlevels-1)) + qlevels[i] = dv100_num_qlevels-1; + + qnos[i] = DV100_QLEVEL_QNO(dv100_qlevels[qlevels[i]]); + size[i] = 0; + + /* for each block */ + b = &blks[8*i]; + for (j = 0; j < 8; j++, b++) { + /* accumulate block size into macroblock */ + if(size_cache[8*i+j][qlevels[i]] == 0) { + /* it is safe to use actual_quantize() here because we only go from finer to coarser, + and it saves the final actual_quantize() down below */ + size_cache[8*i+j][qlevels[i]] = dv100_actual_quantize(b, qlevels[i]); + } + size[i] += size_cache[8*i+j][qlevels[i]]; + } /* for each block */ + + } while ((vs_total_ac_bits < (size[0] + size[1] + size[2] + size[3] + size[4])) && + ((qlevels[0] < (dv100_num_qlevels-1)) || (qlevels[1] < (dv100_num_qlevels-1)) || (qlevels[2] < (dv100_num_qlevels-1)) || (qlevels[3] < (dv100_num_qlevels-1)) || (qlevels[4] < (dv100_num_qlevels-1)))); + + // can we go finer? + } else if(enable_finer && + ((size[0]+size[1]+size[2]+size[3]+size[4]) < vs_total_ac_bits)) { + + int save_qlevel; + int largest = (size[0] % 5); /* 'random' number */ + + while((qlevels[0] > min_qlevel[0]) || + (qlevels[1] > min_qlevel[1]) || + (qlevels[2] > min_qlevel[2]) || + (qlevels[3] > min_qlevel[3]) || + (qlevels[4] > min_qlevel[4])) { + + /* find the macroblock with the highest qlevel */ + for (i = 0; i < 5; i++) { + if ((qlevels[i] > min_qlevel[i]) && (qlevels[i] > qlevels[largest])) + largest = i; + } + + i = largest; + + /* ensure that we don't enter infinite loop */ + largest = (largest+1) % 5; + + if (qlevels[i] <= min_qlevel[i]) { + /* can't unquantize any more */ + continue; + } + + /* quantize a little bit less */ + save_qlevel = qlevels[i]; + qlevels[i] -= dv100_qlevel_inc; + if (qlevels[i] < min_qlevel[i]) + qlevels[i] = min_qlevel[i]; + + qnos[i] = DV100_QLEVEL_QNO(dv100_qlevels[qlevels[i]]); + + size[i] = 0; + + /* for each block */ + b = &blks[8*i]; + for (j = 0; j < 8; j++, b++) { + /* accumulate block size into macroblock */ + if(size_cache[8*i+j][qlevels[i]] == 0) { + size_cache[8*i+j][qlevels[i]] = dv100_actual_quantize(b, qlevels[i]); + } + size[i] += size_cache[8*i+j][qlevels[i]]; + } /* for each block */ + + /* did we bust the limit? */ + if(vs_total_ac_bits < (size[0] + size[1] + size[2] + size[3] + size[4])) { + /* go back down and exit */ + qlevels[i] = save_qlevel; + qnos[i] = DV100_QLEVEL_QNO(dv100_qlevels[qlevels[i]]); + break; + } + } + } + + /* now do the actual quantization */ + for(i = 0; i < 5; i++) { + /* for each block */ + b = &blks[8*i]; + size[i] = 0; + for (j = 0; j < 8; j++, b++) { + /* accumulate block size into macroblock */ + size[i] += dv100_actual_quantize(b, qlevels[i]); + } /* for each block */ + qno_memory[i] = qlevels[i]; + } +} + +/* update all cno values into the blocks, over-writing the old values without + touching anything else. (only used for DV100) */ +static inline void dv_revise_cnos(uint8_t *dif, EncBlockInfo *blk, const DVprofile *profile) +{ + uint8_t *data; + int mb_index, j; + + for (mb_index = 0; mb_index < 5; mb_index++) { + data = dif + mb_index*80 + 4; + for (j = 0; j < profile->bpm; j++) { + /* zero out the class number */ + data[1] &= 0xCF; + /* add the new one */ + data[1] |= blk[profile->bpm*mb_index+j].cno << 4; + + data += profile->block_sizes[j]/8; + } + } +} + static inline void dv_encode_video_segment(DVVideoContext *s, uint8_t *dif, - const uint16_t *mb_pos_ptr) + const int mb_pos_ptr[10], + int qno_memory[5]) { - int mb_index, i, j, v; + int mb_index, i, j; int mb_x, mb_y, c_offset, linesize; uint8_t* y_ptr; uint8_t* data; uint8_t* ptr; int do_edge_wrap; DECLARE_ALIGNED_16(DCTELEM, block[64]); - EncBlockInfo enc_blks[5*6]; - PutBitContext pbs[5*6]; + EncBlockInfo enc_blks[5*DV_MAX_BPM]; + PutBitContext pbs[5*DV_MAX_BPM]; PutBitContext* pb; EncBlockInfo* enc_blk; int vs_bit_size = 0; @@ -851,25 +1322,48 @@ enc_blk = &enc_blks[0]; pb = &pbs[0]; 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) { + + /* DV100 DCT mode is per-macroblock, not per-block */ + int dv100_dct_mode = 0; + + mb_x = *mb_pos_ptr++; + mb_y = *mb_pos_ptr++; + if (s->sys->pix_fmt == PIX_FMT_YUV422P) { y_ptr = s->picture.data[0] + (mb_y * s->picture.linesize[0] * 8) + (mb_x * 4); - } else { /* 4:1:1 */ + } else { /* 4:1:1 or 4:2:0 */ y_ptr = s->picture.data[0] + (mb_y * s->picture.linesize[0] * 8) + (mb_x * 8); } - if (s->sys->pix_fmt == PIX_FMT_YUV420P) { + if (s->sys->pix_fmt == PIX_FMT_YUV420P) { c_offset = (((mb_y >> 1) * s->picture.linesize[1] * 8) + ((mb_x >> 1) * 8)); } else { /* 4:2:2 or 4:1:1 */ c_offset = ((mb_y * s->picture.linesize[1] * 8) + ((mb_x >> 2) * 8)); } do_edge_wrap = 0; - qnos[mb_index] = 15; /* No quantization */ + /* Start with no quantization (15 for 25/50Mbps, 1 for 100Mbps) */ + qnos[mb_index] = DV_PROFILE_IS_HD(s->sys) ? 1 : 15; ptr = dif + mb_index*80 + 4; - for(j = 0;j < 6; j++) { + for(j = 0;j < s->sys->bpm; j++) { int dummy = 0; - if (s->sys->pix_fmt == PIX_FMT_YUV422P) { /* 4:2:2 */ + if (DV_PROFILE_IS_HD(s->sys)) { /* all HD formats */ + if (j < 4) { /* Four Y blocks */ + /* NOTE: at bottom of image in 1080i50/60, the macroblock is handled as 411 */ + if (s->sys->height == 1080 && mb_y == 134) { + data = y_ptr + (j * 8); + } else { + data = y_ptr + ((j & 1) * 8) + ((j >> 1) * 8 * s->picture.linesize[0]); + } + linesize = s->picture.linesize[0]; + } else { /* Cr and Cb blocks */ + int chan = 2 - ((j-4)>>1); + if (s->sys->height == 1080 && mb_y == 134) { + /* bottom edge: horizontal row of 2 blocks */ + data = s->picture.data[chan] + c_offset + ((j&1) * 8); + } else { + data = s->picture.data[chan] + c_offset + ((j&1) * 8 * s->picture.linesize[chan]); + } + linesize = s->picture.linesize[chan]; + } + } else if (s->sys->pix_fmt == PIX_FMT_YUV422P) { /* 4:2:2 */ if (j == 0 || j == 2) { /* Y0 Y1 */ data = y_ptr + ((j>>1) * 8); @@ -902,6 +1396,29 @@ } } + /* decide whether to use DV100 field macroblock mode */ + /* note that 4x1 "bottom macro blocks" cannot use field mode */ + if ((s->sys->height == 1080) && (j == 0) && + /* some decoders appear not to support field mode in the entire + 1080i60 A0-A16 or 1080i50 A0-A1 regions, even though not all + of those macroblocks are "bottom macro blocks" */ + ((DV_PROFILE_IS_1080i50(s->sys) && (mb_y != 0) && (mb_y != 134)) || + (DV_PROFILE_IS_1080i60(s->sys) && (mb_y >= 8) && (mb_y < 128))) + && (s->avctx->flags & CODEC_FLAG_INTERLACED_DCT)) { + /* XXX could have a better heuristic for this */ + int p = 0, q = 0, line; + for (line=0;line<6;line++) { + for (i=0;i<8;i++) { + int dp, dq; + dp = data[(line+0)*linesize+i] - data[(line+1)*linesize+i]; + dq = data[(line+0)*linesize+i] - data[(line+2)*linesize+i]; + p += dp*dp; + q += dq*dq; + } + } + dv100_dct_mode = (p>(q-100)); + } + /* Everything is set up -- now just copy data -> DCT block */ if (do_edge_wrap) { /* Edge wrap copy: 4x16 -> 8x8 */ uint8_t* d; @@ -913,12 +1430,45 @@ data += linesize; b += 8; } + } else if (dv100_dct_mode) { /* DV100 field DCT */ + DCTELEM *b = block; + uint8_t *data0, *data1, *d; + int off; + if (s->sys->height == 1080 && mb_y == 134) { + off = 16; + } else { + off = 8*linesize; + } + if(j < 2 || j == 4 || j == 6) { + data0 = data; + data1 = data + off; + } else { + data0 = data - off; + data1 = data; + data0 += linesize; + data1 += linesize; + } + d = data0; + for (i=0;i<4;i++) { + b[0] = d[0]; b[1] = d[1]; b[2] = d[2]; b[3] = d[3]; + b[4] = d[4]; b[5] = d[5]; b[6] = d[6]; b[7] = d[7]; + b += 8; + d += 2*linesize; + } + d = data1; + for (i=0;i<4;i++) { + b[0] = d[0]; b[1] = d[1]; b[2] = d[2]; b[3] = d[3]; + b[4] = d[4]; b[5] = d[5]; b[6] = d[6]; b[7] = d[7]; + b += 8; + d += 2*linesize; + } } else { /* Simple copy: 8x8 -> 8x8 */ if (!dummy) s->get_pixels(block, data, linesize); } - if(s->avctx->flags & CODEC_FLAG_INTERLACED_DCT) + if((s->avctx->flags & CODEC_FLAG_INTERLACED_DCT) && + !DV_PROFILE_IS_HD(s->sys)) enc_blk->dct_mode = dv_guess_dct_mode(block); else enc_blk->dct_mode = 0; @@ -935,73 +1485,505 @@ s->fdct[enc_blk->dct_mode](block); } - dv_set_class_number(block, enc_blk, - enc_blk->dct_mode ? ff_zigzag248_direct : ff_zigzag_direct, - enc_blk->dct_mode ? dv_weight_248 : dv_weight_88, - j/4); + if (DV_PROFILE_IS_HD(s->sys)) { + const int *weights; + if (s->sys->height == 1080) { + weights = (j < 4) ? dv_weight_1080_y : dv_weight_1080_c; + } else { /* 720p */ + weights = (j < 4) ? dv_weight_720_y : dv_weight_720_c; + } + dv_set_class_number_hd(block, enc_blk, + ff_zigzag_direct, + weights, + dv100_min_bias+(j>>2)*dv100_chroma_bias); + } else { + dv_set_class_number_sd(block, enc_blk, + enc_blk->dct_mode ? ff_zigzag248_direct : ff_zigzag_direct, + enc_blk->dct_mode ? dv_weight_248 : dv_weight_88, + j>>2); + } - init_put_bits(pb, ptr, block_sizes[j]/8); + init_put_bits(pb, ptr, s->sys->block_sizes[j]/8); + put_bits(pb, 9, (uint16_t)(((enc_blk->mb[0] >> 3) - 1024 + 2) >> 2)); - put_bits(pb, 1, enc_blk->dct_mode); + put_bits(pb, 1, DV_PROFILE_IS_HD(s->sys) ? ((j == 0) ? dv100_dct_mode : 1) : enc_blk->dct_mode); put_bits(pb, 2, enc_blk->cno); vs_bit_size += enc_blk->bit_size[0] + enc_blk->bit_size[1] + enc_blk->bit_size[2] + enc_blk->bit_size[3]; ++enc_blk; ++pb; - ptr += block_sizes[j]/8; + ptr += s->sys->block_sizes[j]/8; } } - if (vs_total_ac_bits < vs_bit_size) - dv_guess_qnos(&enc_blks[0], &qnos[0]); + if (DV_PROFILE_IS_HD(s->sys)) { + /* unconditional */ + dv_guess_qnos_hd(&enc_blks[0], &qnos[0], s->sys->vs_total_ac_bits, qno_memory); + } else if (s->sys->vs_total_ac_bits < vs_bit_size) { + dv_guess_qnos_sd(&enc_blks[0], &qnos[0], s->sys->vs_total_ac_bits); + } for (i=0; i<5; i++) { dif[i*80 + 3] = qnos[i]; } /* First pass over individual cells only */ - for (j=0; j<5*6; j++) + for (j=0; j<5*s->sys->bpm; j++) dv_encode_ac(&enc_blks[j], &pbs[j], &pbs[j+1]); /* Second pass over each MB space */ - for (j=0; j<5*6; j+=6) { + for (j=0; j<5*s->sys->bpm; j+=s->sys->bpm) { pb= &pbs[j]; - for (i=0; i<6; i++) { + for (i=0; isys->bpm; i++) { if (enc_blks[i+j].partial_bit_count) - pb=dv_encode_ac(&enc_blks[i+j], pb, &pbs[j+6]); + pb=dv_encode_ac(&enc_blks[i+j], pb, &pbs[j+s->sys->bpm]); } } /* Third and final pass over the whole vides segment space */ pb= &pbs[0]; - for (j=0; j<5*6; j++) { + for (j=0; j<5*s->sys->bpm; j++) { if (enc_blks[j].partial_bit_count) - pb=dv_encode_ac(&enc_blks[j], pb, &pbs[6*5]); + pb=dv_encode_ac(&enc_blks[j], pb, &pbs[s->sys->bpm*5]); if (enc_blks[j].partial_bit_count) av_log(NULL, AV_LOG_ERROR, "ac bitstream overflow\n"); } - for (j=0; j<5*6; j++) + for (j=0; j<5*s->sys->bpm; j++) flush_put_bits(&pbs[j]); + + if (DV_PROFILE_IS_HD(s->sys)) + dv_revise_cnos(dif, enc_blks, s->sys); } +/* macroblock permutations common to all formats */ +static const uint8_t super_x_order[] = {2,1,3,0,4}; +static const uint8_t super_y_bases[] = {2,6,8,0,4}; + +void find_macroblock_dv25_411(const struct DVprofile *sys, int channel, int seq, int av, int seg, int mbloc[10]) +{ + /* starting x coordinate of horizontal superblocks, in units of blocks */ + static const uint8_t super_x_starts[] = {0,4,9,13,18}; + + int mb_index; + int *mb = &mbloc[0]; + for (mb_index = 0; mb_index < 5; mb_index++, mb += 2) { + /* index of this block within the DIF sequence (0-135) */ + int vid_block_num = av*15 + seg*5 + mb_index; + + /* X and Y indices of the superblock we're inside */ + int super_x = super_x_order[vid_block_num % 5]; + int super_y = (super_y_bases[vid_block_num % 5] + seq) % sys->difseg_size; + + /* index within the superblock */ + int within_super = vid_block_num / 5; + + /* locate us within the superblock's "Tetris" pattern */ + int within_super_x, within_super_y; + + if (super_x & 1) { + /* super_x is ODD */ + if (within_super < 3) { + within_super_x = 0; + within_super_y = 3 + within_super; + } else if (within_super < 9) { + within_super_x = 1; + within_super_y = 5 - (within_super-3); + } else if (within_super < 15) { + within_super_x = 2; + within_super_y = (within_super-9); + } else if (within_super < 21) { + within_super_x = 3; + within_super_y = 5 - (within_super-15); + } else { + within_super_x = 4; + within_super_y = (within_super-21); + } + } else { + /* super_x is EVEN */ + if (within_super < 6) { + within_super_x = 0; + within_super_y = within_super; + } else if (within_super < 12) { + within_super_x = 1; + within_super_y = 5 - (within_super-6); + } else if (within_super < 18) { + within_super_x = 2; + within_super_y = (within_super - 12); + } else if (within_super < 24) { + within_super_x = 3; + within_super_y = 5 - (within_super-18); + } else { + within_super_x = 4; + within_super_y = (within_super-24); + /* special case for rightmost superblock */ + if (super_x == 4) { + within_super_y *= 2; + } + } + } + + mb[0] = 4*(super_x_starts[super_x] + within_super_x); + mb[1] = 6*super_y + within_super_y; + } +} + +/* return x,y given an index into the 9x3 brick pattern */ +static void macroblock_brick_pattern(int within_super, int *within_super_x, int *within_super_y) +{ + if (within_super < 3) { + *within_super_x = 0; + *within_super_y = within_super; + } else if (within_super < 6) { + *within_super_x = 1; + *within_super_y = 2 - (within_super-3); + } else if (within_super < 9) { + *within_super_x = 2; + *within_super_y = (within_super-6); + } else if (within_super < 12) { + *within_super_x = 3; + *within_super_y = 2 - (within_super-9); + } else if (within_super < 15) { + *within_super_x = 4; + *within_super_y = (within_super-12); + } else if (within_super < 18) { + *within_super_x = 5; + *within_super_y = 2 - (within_super-15); + } else if (within_super < 21) { + *within_super_x = 6; + *within_super_y = (within_super-18); + } else if (within_super < 24) { + *within_super_x = 7; + *within_super_y = 2 - (within_super-21); + } else { + *within_super_x = 8; + *within_super_y = (within_super-24); + } +} + +void find_macroblock_dv25_420(const struct DVprofile *sys, int channel, int seq, int av, int seg, int mbloc[10]) +{ + int mb_index; + int *mb = &mbloc[0]; + for (mb_index = 0; mb_index < 5; mb_index++, mb += 2) { + /* index of this block within the DIF sequence (0-135) */ + int vid_block_num = av*15 + seg*5 + mb_index; + + /* X and Y indices of the superblock we're inside */ + int super_x = super_x_order[vid_block_num % 5]; + int super_y = (super_y_bases[vid_block_num % 5] + seq) % sys->difseg_size; + + /* index within the superblock */ + int within_super = vid_block_num / 5; + + /* locate us within the superblock's "brick" pattern */ + int within_super_x, within_super_y; + + macroblock_brick_pattern(within_super, &within_super_x, &within_super_y); + + mb[0] = 2*(9*super_x + within_super_x); + mb[1] = 2*(3*super_y + within_super_y); + } +} + +void find_macroblock_dv50(const struct DVprofile *sys, int channel, int seq, int av, int seg, int mbloc[10]) +{ + int mb_index; + int *mb = &mbloc[0]; + for (mb_index = 0; mb_index < 5; mb_index++, mb += 2) { + + /* index of this block within the DIF sequence (0-135) */ + int vid_block_num = av*15 + seg*5 + mb_index; + + int ysupers = 2 * sys->difseg_size; + + /* X and Y indices of the superblock we're inside */ + int super_x = super_x_order[vid_block_num % 5]; + int super_y = (2*(super_y_bases[vid_block_num % 5] + seq) + channel) % ysupers; + + /* index within the superblock */ + int within_super = vid_block_num / 5; + + /* locate us within the superblock's "brick" pattern */ + int within_super_x, within_super_y; + + macroblock_brick_pattern(within_super, &within_super_x, &within_super_y); + + /* macroblocks are 16x8 pixels */ + mb[0] = 4*(9*super_x + within_super_x); + mb[1] = (3*super_y + within_super_y); + } +} + +void find_macroblock_dv100_1080i60(const struct DVprofile *sys, int channel, int seq, int av, int seg, int mbloc[10]) +{ + /* starting 't' values indexed by DIF sequence */ + static const uint8_t t_starts[] = {0,2,4,1,3,0,2,4,1,3}; + + int mb_index; + int *mb = &mbloc[0]; + for (mb_index = 0; mb_index < 5; mb_index++, mb += 2) { + /* one "divided block" h per channel (0-3) */ + int hx = channel & 1; + int hy = channel >>1; + + /* X and Y indices of the superblock we're inside */ + /* superblocks are 9x3 blocks */ + int super_x = super_x_order[mb_index]; + + /* the superblock y coordinates use a permutation */ + + int s = seq/5; /* first half of channel? */ + int t = (t_starts[seq] + av*3 + seg) % 5; + + int super_y = (super_y_bases[mb_index] + 4*channel + s + 2*t) % 10; + + /* index within the superblock */ + int within_super = ((av*3 + seg + 27*seq)/5) % 27; + + /* locate us within the superblock's "brick" pattern */ + int within_super_x = within_super % 9; + int within_super_y = within_super / 9; + + /* block x,y coordinates within divided block */ + int divblock_x = (9*super_x + within_super_x); + int divblock_y = (3*super_y + within_super_y); + + /* coordinates within rearranged frame */ + int re_x = 18*(divblock_x/9) + 9*hx + (divblock_x % 9); + int re_y = 2*divblock_y + hy; + + /* de-rearrange the macroblock */ + int block_x, block_y; + if (re_x >= 80) { + /* right edge strip */ + if (re_y < 32) { + /* A0-A7 */ + block_x = 10 * (re_y/4) + (re_x-80); + block_y = re_y % 4; + } else if (re_y < 56) { + /* A8-A15 */ + block_x = 10*((re_y-32)/3) + (re_x - 80); + block_y = 64 + (re_y-32) % 3; + } else { + /* B16 */ + block_x = 10*(re_y-56) + ((re_x - 80) % 10); + block_x *= 2; /* B blocks are twice as wide as A blocks */ + block_y = 67; + } + } else { + block_x = re_x; + block_y = re_y + 4; + } + + /* macroblocks are 16x16 pixels */ + mb[0] = 4*block_x; + mb[1] = 2*block_y; + } +} + +void find_macroblock_dv100_1080i50(const struct DVprofile *sys, int channel, int seq, int av, int seg, int mbloc[10]) +{ + int mb_index; + int *mb = &mbloc[0]; + for (mb_index = 0; mb_index < 5; mb_index++, mb += 2) { + /* one "divided block" h per channel (0-3) */ + int hx = channel & 1; + int hy = channel >>1; + + /* X and Y indices of the superblock we're inside */ + /* superblocks are 9x3 blocks */ + int super_x, super_y; + + /* index within the superblock */ + int within_super; + + /* macroblock location */ + int block_x, block_y; + + if (channel == 0 && seq == 11) { /* edge unit */ + super_x = mb_index; + super_y = 0; + + within_super = (av*3 + seg + 27*seq) % 27; + block_x = 27*super_x + within_super; + + if (block_x < 90) { /* A0 */ + block_y = 0; + } else { /* A1 */ + /* A1 macroblocks are wide and short */ + block_x = 2*(block_x-90); + block_y = 67; + } + } else { + static const int super_y_pattern[] = {0,5,10,4,9,3,8,2,7,1,6}; + int within_super_x, within_super_y; + int divblock_x, divblock_y; + int re_x, re_y; + + super_x = super_x_order[mb_index]; + + /* the superblock y coordinates use a permutation */ + super_y = (super_y_bases[mb_index] + super_y_pattern[(seq+3*channel)%11] + seg + av*3) % 11; + + within_super = ((av*3 + seg + 27*seq)/11) % 27; + + /* locate us within the superblock's "brick" pattern */ + within_super_x = within_super % 9; + within_super_y = within_super / 9; + + /* block x,y coordinates within divided block */ + divblock_x = (9*super_x + within_super_x); + divblock_y = (3*super_y + within_super_y); + + /* coordinates within rearranged frame */ + re_x = 18*(divblock_x/9) + 9*hx + (divblock_x % 9); + re_y = 2*divblock_y + hy; + + block_x = re_x; + block_y = re_y + 1; + assert(block_x >= 0 && block_x < 90); + assert(block_y >= 0 && block_y < 67); + } + + /* macroblocks are 16x16 pixels */ + mb[0] = 4*block_x; + mb[1] = 2*block_y; + } +} + +void find_macroblock_dv100_720p60(const struct DVprofile *sys, int channel, int seq, int av, int seg, int mbloc[10]) +{ + /* starting 't' values indexed by DIF sequence */ + static const uint8_t t_starts[] = {0,2,4,1,3,0,2,4,1,3}; + + int mb_index; + int *mb = &mbloc[0]; + for (mb_index = 0; mb_index < 5; mb_index++, mb += 2) { + /* one "divided block" h per channel (0-3) */ + int hx = channel & 1; + int hy = channel >>1; + + /* X and Y indices of the superblock we're inside */ + /* superblocks are 9x3 blocks */ + int super_x = super_x_order[mb_index]; + + /* the superblock y coordinates use a permutation */ + + int s = seq/5; /* first half of channel? */ + int t = (t_starts[seq] + av*3 + seg) % 5; + + int super_y = (super_y_bases[mb_index] + 4*channel + s + 2*t) % 10; + + /* index within the superblock */ + int within_super = ((av*3 + seg + 27*seq)/5) % 27; + + /* locate us within the superblock's "tetris" pattern */ + int within_super_x, within_super_y; + int divblock_x, divblock_y; + int block_x, block_y; + + if (super_y & 1) { /* lower tetris */ + if (within_super < 3) { + within_super_x = 3 + within_super; + within_super_y = 4; + } else if (within_super < 9) { + within_super_x = within_super - 3; + within_super_y = 5; + } else if (within_super < 15) { + within_super_x = within_super - 9; + within_super_y = 6; + } else if (within_super < 21) { + within_super_x = within_super - 15; + within_super_y = 7; + } else { + within_super_x = within_super - 21; + within_super_y = 8; + } + } else { /* upper tetris */ + if (within_super < 6) { + within_super_x = within_super; + within_super_y = 0; + } else if (within_super < 12) { + within_super_x = within_super - 6; + within_super_y = 1; + } else if (within_super < 18) { + within_super_x = within_super - 12; + within_super_y = 2; + } else if (within_super < 24) { + within_super_x = within_super - 18; + within_super_y = 3; + } else { + within_super_x = within_super - 24; + within_super_y = 4; + } + } + + /* block x,y coordinates within divided block */ + divblock_x = (6*super_x + within_super_x); + divblock_y = (9*(super_y>>1) + within_super_y); + + /* coordinates within rearranged frame */ + block_x = 12*(divblock_x/6) + 6*hx + (divblock_x % 6); + block_y = divblock_y + 45*hy; + + /* macroblocks are 16x16 pixels */ + mb[0] = 4*block_x; + mb[1] = 2*block_y; + } +} + static int dv_decode_mt(AVCodecContext *avctx, void* sl) { DVVideoContext *s = avctx->priv_data; - int slice = (size_t)sl; + int i; - /* which DIF channel is this? */ - int chan = slice / (s->sys->difseg_size * 27); + for (i = 0; i < s->sys->n_difchan*27; i++) { + int slice = ((size_t)sl)*s->sys->n_difchan*27 + i; - /* slice within the DIF channel */ - int chan_slice = slice % (s->sys->difseg_size * 27); + /* which DIF channel is this? */ + int chan = slice / (s->sys->difseg_size * 27); - /* byte offset of this channel's data */ - int chan_offset = chan * s->sys->difseg_size * 150 * 80; + /* slice within the DIF channel */ + int chan_slice = slice % (s->sys->difseg_size * 27); - dv_decode_video_segment(s, &s->buf[((chan_slice/27)*6+(chan_slice/3)+chan_slice*5+7)*80 + chan_offset], - &s->sys->video_place[slice*5]); + /* DIF sequence */ + int seq = chan_slice / 27; + + /* AV sequence */ + int av = (chan_slice/3) % 9; + + /* video segment */ + int seg = chan_slice % 3; + + /* byte offset of this channel's data */ + int chan_offset = chan * s->sys->difseg_size * 150 * 80; + + /* first byte of first DIF block in this video segment */ + uint8_t *dif = &s->buf[((chan_slice/27)*6+(chan_slice/3)+chan_slice*5+7)*80 + chan_offset]; + + /* macroblock locations (x,y for each of the 5 macroblocks) */ + int mbloc[5*2]; + + /* in 1080i50, channel !=0 / seq == 11 are unused */ + if (DV_PROFILE_IS_1080i50(s->sys) && chan != 0 && seq == 11) + continue; + + if (s->sys->find_macroblock) { + s->sys->find_macroblock(s->sys, chan, seq, av, seg, mbloc); + } else { + int i; + int *mb = &mbloc[0]; + for (i = 0; i < 5; i++, mb += 2) { + uint32_t v = s->sys->video_place[slice*5 + i]; + mb[0] = v & 0xff; + mb[1] = v >> 8; + } + } + + dv_decode_video_segment(s, dif, mbloc); + } return 0; } @@ -1009,26 +1991,72 @@ static int dv_encode_mt(AVCodecContext *avctx, void* sl) { DVVideoContext *s = avctx->priv_data; - int slice = (size_t)sl; + /* maintain QNOs used for last set of macroblocks + as a starting point for future macroblocks + (for speed optimization only, doesn't affect quality) */ + int qno_memory[5]; + int i; - /* which DIF channel is this? */ - int chan = slice / (s->sys->difseg_size * 27); + for (i = 0; i < 5; i++) + qno_memory[i] = dv100_starting_qno; - /* slice within the DIF channel */ - int chan_slice = slice % (s->sys->difseg_size * 27); + for (i = 0; i < s->sys->n_difchan*27; i++) { + int slice = ((size_t)sl)*s->sys->n_difchan*27 + i; - /* byte offset of this channel's data */ - int chan_offset = chan * s->sys->difseg_size * 150 * 80; + /* which DIF channel is this? */ + int chan = slice / (s->sys->difseg_size * 27); - dv_encode_video_segment(s, &s->buf[((chan_slice/27)*6+(chan_slice/3)+chan_slice*5+7)*80 + chan_offset], - &s->sys->video_place[slice*5]); + /* slice within the DIF channel */ + int chan_slice = slice % (s->sys->difseg_size * 27); + + /* DIF sequence */ + int seq = chan_slice / 27; + + /* AV sequence */ + int av = (chan_slice/3) % 9; + + /* video segment */ + int seg = chan_slice % 3; + + /* byte offset of this channel's data */ + int chan_offset = chan * s->sys->difseg_size * 150 * 80; + + /* first byte of first DIF block in this video segment */ + uint8_t *dif = &s->buf[((chan_slice/27)*6+(chan_slice/3)+chan_slice*5+7)*80 + chan_offset]; + + /* macroblock locations (x,y for each of the 5 macroblocks) */ + int mbloc[5*2]; + + /* in 1080i50, channel !=0 / seq == 11 are unused */ + if (DV_PROFILE_IS_1080i50(s->sys) && chan != 0 && seq == 11) { + /* clear the dummy DIF blocks */ + int b; + for (b = 0; b < 5; b++, dif += 80) + memset(dif+3, 0xff, 77); + continue; + } + + if (s->sys->find_macroblock) { + s->sys->find_macroblock(s->sys, chan, seq, av, seg, mbloc); + } else { + int i; + int *mb = &mbloc[0]; + for (i = 0; i < 5; i++, mb += 2) { + uint32_t v = s->sys->video_place[slice*5 + i]; + mb[0] = v & 0xff; + mb[1] = v >> 8; + } + } + + dv_encode_video_segment(s, dif, mbloc, qno_memory); + } return 0; } #endif #ifdef CONFIG_DECODERS /* NOTE: exactly one frame must be given (120000 bytes for NTSC, - 144000 bytes for PAL - or twice those for 50Mbps) */ + 144000 bytes for PAL - or twice those for 50Mbps - or 4x for 100Mbps) */ static int dvvideo_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size) @@ -1055,8 +2083,7 @@ s->picture.top_field_first = 0; s->buf = buf; - avctx->execute(avctx, dv_decode_mt, (void**)&dv_anchor[0], NULL, - s->sys->n_difchan * s->sys->difseg_size * 27); + avctx->execute(avctx, dv_decode_mt, (void**)&dv_anchor[0], NULL, s->sys->difseg_size); emms_c(); @@ -1069,33 +2096,29 @@ #endif -static inline int dv_write_pack(enum dv_pack_type pack_id, DVVideoContext *c, uint8_t* buf) +static int dv_write_pack(enum dv_pack_type pack_id, DVVideoContext *c, uint8_t* buf, int seq) { - /* - * Here's what SMPTE314M says about these two: - * (page 6) APTn, AP1n, AP2n, AP3n: These data shall be identical - * as track application IDs (APTn = 001, AP1n = - * 001, AP2n = 001, AP3n = 001), if the source signal - * comes from a digital VCR. If the signal source is - * unknown, all bits for these data shall be set to 1. - * (page 12) STYPE: STYPE defines a signal type of video signal - * 00000b = 4:1:1 compression - * 00100b = 4:2:2 compression - * XXXXXX = Reserved - * Now, I've got two problems with these statements: - * 1. it looks like APT == 111b should be a safe bet, but it isn't. - * It seems that for PAL as defined in IEC 61834 we have to set - * APT to 000 and for SMPTE314M to 001. - * 2. It is not at all clear what STYPE is used for 4:2:0 PAL - * compression scheme (if any). - */ - int apt = (c->sys->pix_fmt == PIX_FMT_YUV420P ? 0 : 1); - int stype = (c->sys->pix_fmt == PIX_FMT_YUV422P ? 4 : 0); + int apt; + uint8_t aspect; - uint8_t aspect = 0; - if((int)(av_q2d(c->avctx->sample_aspect_ratio) * c->avctx->width / c->avctx->height * 10) == 17) /* 16:9 */ - aspect = 0x02; + /* Its hard to tell what SMPTE requires w.r.t. APT, but Quicktime needs it. + * We set it based on pix_fmt value but it really should be per DV profile */ + if (DV_PROFILE_IS_HD(c->sys)) { + apt = 0; + } else { + apt = (c->sys->pix_fmt == PIX_FMT_YUV422P ? 1 : 0); + } + if (DV_PROFILE_IS_HD(c->sys)) { + /* HD formats are always 16:9 */ + aspect = 0x07; + } else { + aspect = 0; /* 4:3 is the default*/ + if((int)(av_q2d(c->avctx->sample_aspect_ratio) * c->avctx->width / c->avctx->height * 10) == 17) /* 16:9 */ + aspect = 0x07; // REGRESSION: 0x02??? + } + + buf[0] = (uint8_t)pack_id; switch (pack_id) { case dv_header525: /* I can't imagine why these two weren't defined as real */ @@ -1120,7 +2143,7 @@ 0xf; /* reserved -- always 1 */ buf[3] = (3 << 6) | /* reserved -- always 1 */ (c->sys->dsf << 5) | /* system: 60fields/50fields */ - stype; /* signal type video compression */ + c->sys->video_stype; /* signal type video compression */ buf[4] = 0xff; /* VISC: 0xff -- no information */ break; case dv_video_control: @@ -1151,7 +2174,7 @@ /* 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 += dv_write_pack((c->sys->dsf ? dv_header625 : dv_header525), c, buf, i); buf += 72; /* unused bytes */ /* DV subcode: 2DIFs */ @@ -1165,11 +2188,11 @@ /* DV VAUX: 3DIFS */ for (j = 0; j < 3; j++) { buf += dv_write_dif_id(dv_sect_vaux, chan, i, j, buf); - buf += dv_write_pack(dv_video_source, c, buf); - buf += dv_write_pack(dv_video_control, c, buf); + buf += dv_write_pack(dv_video_source, c, buf, i); + buf += dv_write_pack(dv_video_control, c, buf, i); buf += 7*5; - buf += dv_write_pack(dv_video_source, c, buf); - buf += dv_write_pack(dv_video_control, c, buf); + buf += dv_write_pack(dv_video_source, c, buf, i); + buf += dv_write_pack(dv_video_control, c, buf, i); buf += 4*5 + 2; /* unused bytes */ } @@ -1209,8 +2232,7 @@ s->picture.pict_type = FF_I_TYPE; s->buf = buf; - c->execute(c, dv_encode_mt, (void**)&dv_anchor[0], NULL, - s->sys->n_difchan * s->sys->difseg_size * 27); + c->execute(c, dv_encode_mt, (void**)&dv_anchor[0], NULL, s->sys->difseg_size); emms_c(); Index: libavcodec/dvdata.h =================================================================== --- libavcodec/dvdata.h (revision 11056) +++ libavcodec/dvdata.h (working copy) @@ -38,6 +38,7 @@ */ typedef struct DVprofile { int dsf; /* value of the dsf in the DV header */ + int video_stype; /* stype for VAUX source pack */ int frame_size; /* total size of one frame in bytes */ int difseg_size; /* number of DIF segments per DIF channel */ int n_difchan; /* number of DIF channels per frame */ @@ -47,8 +48,15 @@ int height; /* picture height in pixels */ int width; /* picture width in pixels */ AVRational sar[2]; /* sample aspect ratios for 4:3 and 16:9 */ - const uint16_t *video_place; /* positions of all DV macro blocks */ + const uint16_t *video_place; /* positions of all DV macro blocks XXX remove this */ + + /* return macroblock location, in multiples of blocks (5 macroblocks at a time, (x,y) in mbloc[]) */ + void (*find_macroblock)(const struct DVprofile*, int channel, int seq, int av, int seg, int mbloc[10]); + enum PixelFormat pix_fmt; /* picture pixel format */ + int bpm; /* blocks per macroblock */ + const uint8_t *block_sizes; /* AC block sizes, in bits */ + int vs_total_ac_bits; /* bit budget for AC only in 5 blocks */ int audio_stride; /* size of audio_shuffle table */ int audio_min_samples[3];/* min ammount of audio samples */ @@ -60,6 +68,114 @@ #define NB_DV_VLC 409 +/* maximum number of blocks per macroblock in any DV format */ +#define DV_MAX_BPM 8 + +/* DV100 quantization tables */ + +/* setting this to 1 results in a faster codec but + * somewhat lower image quality */ +#define DV100_SACRIFICE_QUALITY_FOR_SPEED 1 + +/* quantization quanta by QNO for DV100 */ +static const uint8_t dv100_qstep[16] = { + 1, // QNO = 0 and 1 both have no quantization + 1, + 2, 3, 4, 5, 6, 7, 8, 16, 18, 20, 22, 24, 28, 52 +}; + +/* pack combination of QNO and CNO into a single 8-bit value */ +#define DV100_MAKE_QLEVEL(qno,cno) ((qno<<2) | (cno)) +#define DV100_QLEVEL_QNO(qlevel) (qlevel>>2) +#define DV100_QLEVEL_CNO(qlevel) (qlevel&0x3) + +/* The quantization step is determined by a combination of QNO and + CNO. We refer to these combinations as "qlevels" (this term is our + own, it's not mentioned in the spec). We use CNO, a multiplier on + the quantization step, to "fill in the gaps" between quantization + steps associated with successive values of QNO. e.g. there is no + QNO for a quantization step of 10, but we can use QNO=5 CNO=1 to + get the same result. The table below encodes combinations of QNO + and CNO in order of increasing quantization coarseness. */ + +static const uint8_t dv100_qlevels[] = { + DV100_MAKE_QLEVEL( 1,0), // 1*1= 1 + DV100_MAKE_QLEVEL( 1,0), // 1*1= 1 + DV100_MAKE_QLEVEL( 2,0), // 2*1= 2 + DV100_MAKE_QLEVEL( 3,0), // 3*1= 3 + DV100_MAKE_QLEVEL( 4,0), // 4*1= 4 + DV100_MAKE_QLEVEL( 5,0), // 5*1= 5 + DV100_MAKE_QLEVEL( 6,0), // 6*1= 6 + DV100_MAKE_QLEVEL( 7,0), // 7*1= 7 + DV100_MAKE_QLEVEL( 8,0), // 8*1= 8 + DV100_MAKE_QLEVEL( 5,1), // 5*2=10 + DV100_MAKE_QLEVEL( 6,1), // 6*2=12 + DV100_MAKE_QLEVEL( 7,1), // 7*2=14 + DV100_MAKE_QLEVEL( 9,0), // 16*1=16 + DV100_MAKE_QLEVEL(10,0), // 18*1=18 + DV100_MAKE_QLEVEL(11,0), // 20*1=20 + DV100_MAKE_QLEVEL(12,0), // 22*1=22 + DV100_MAKE_QLEVEL(13,0), // 24*1=24 + DV100_MAKE_QLEVEL(14,0), // 28*1=28 + DV100_MAKE_QLEVEL( 9,1), // 16*2=32 + DV100_MAKE_QLEVEL(10,1), // 18*2=36 + DV100_MAKE_QLEVEL(11,1), // 20*2=40 + DV100_MAKE_QLEVEL(12,1), // 22*2=44 + DV100_MAKE_QLEVEL(13,1), // 24*2=48 + DV100_MAKE_QLEVEL(15,0), // 52*1=52 + DV100_MAKE_QLEVEL(14,1), // 28*2=56 + DV100_MAKE_QLEVEL( 9,2), // 16*4=64 + DV100_MAKE_QLEVEL(10,2), // 18*4=72 + DV100_MAKE_QLEVEL(11,2), // 20*4=80 + DV100_MAKE_QLEVEL(12,2), // 22*4=88 + DV100_MAKE_QLEVEL(13,2), // 24*4=96 + // ... + DV100_MAKE_QLEVEL(15,3), // 52*8=416 +}; + +static const int dv100_num_qlevels = sizeof(dv100_qlevels)/sizeof(dv100_qlevels[0]); + +/* how much to increase qlevel when we need to compress more coarsely */ +/* this is a tradeoff between encoding speed and space efficiency */ +/* the highest-quality, lowest-speed option it to use 1 for all qlevels. */ +static const uint8_t dv100_qstep_delta[16] = { +#if DV100_SACRIFICE_QUALITY_FOR_SPEED + 0, 2, 0, 5, 0, 0, 0, 0, 1, 6, 0, 0, 0, 0, 0, 0, +#else + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +#endif +}; + +/* how much to decrease qlevel when we can compress more finely */ +/* must be the "inverse" of dv100_qstep_delta */ +static const uint8_t dv100_qbackstep_delta[16] = { +#if DV100_SACRIFICE_QUALITY_FOR_SPEED + 0, 0, 0, 2, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 0, 6, +#else + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +#endif +}; + +#if DV100_SACRIFICE_QUALITY_FOR_SPEED +static const int dv100_min_bias = 0; +static const int dv100_chroma_bias = 0; +static const int dv100_starting_qno = 1; +static const int dv100_min_qno = 1; +static const int dv100_qlevel_inc = 4; +#else +static const int dv100_min_bias = 0; +static const int dv100_chroma_bias = 0; +static const int dv100_starting_qno = 1; +static const int dv100_min_qno = 1; +static const int dv100_qlevel_inc = 1; +#endif + +// 1/qstep, shifted up by 16 bits +static const int dv100_qstep_bits = 16; +static const int dv100_qstep_inv[16] = { + 65536, 65536, 32768, 21845, 16384, 13107, 10923, 9362, 8192, 4096, 3641, 3277, 2979, 2731, 2341, 1260, +}; + /* * There's a catch about the following three tables: the mapping they establish * between (run, level) and vlc is not 1-1. So you have to watch out for that @@ -1265,8 +1381,6 @@ 0x0834, 0x2320, 0x2f44, 0x3810, 0x1658, }; -/* 4:2:2 macroblock placement tables created by dvtables.py */ - /* 2 channels per frame, 10 DIF sequences per channel, 27 video segments per DIF sequence, 5 macroblocks per video segment */ static const uint16_t dv_place_422_525[2*10*27*5] = { @@ -2510,6 +2624,93 @@ 22017, 25191, 24457, 27962, 22733, 24600, 25971, 29642, }; +/* DV100 weights are pre-zigzagged, inverted and multiplied by 2^(dv100_weight_shift) + (in DV100 the AC components are divided by the spec weights) */ +static const int dv100_weight_shift = 16; +static const int dv_weight_1080_y[64] = { + 8192, 65536, 65536, 61681, 61681, 61681, 58254, 58254, + 58254, 58254, 58254, 58254, 55188, 58254, 58254, 55188, + 55188, 55188, 55188, 55188, 55188, 24966, 27594, 26214, + 26214, 26214, 27594, 24966, 23831, 24385, 25575, 25575, + 25575, 25575, 24385, 23831, 23302, 23302, 24966, 24966, + 24966, 23302, 23302, 21845, 22795, 24385, 24385, 22795, + 21845, 21400, 21845, 23831, 21845, 21400, 10382, 10700, + 10700, 10382, 10082, 9620, 10082, 9039, 9039, 8525, +}; +static const int dv_weight_1080_c[64] = { + 8192, 65536, 65536, 61681, 61681, 61681, 41943, 41943, + 41943, 41943, 40330, 41943, 40330, 41943, 40330, 40330, + 40330, 38836, 38836, 40330, 40330, 24966, 27594, 26214, + 26214, 26214, 27594, 24966, 23831, 24385, 25575, 25575, + 25575, 25575, 24385, 23831, 11523, 11523, 12483, 12483, + 12483, 11523, 11523, 10923, 11275, 12193, 12193, 11275, + 10923, 5323, 5490, 5924, 5490, 5323, 5165, 5323, + 5323, 5165, 5017, 4788, 5017, 4520, 4520, 4263, +}; +static const int dv_weight_720_y[64] = { + 8192, 65536, 65536, 61681, 61681, 61681, 58254, 58254, + 58254, 58254, 58254, 58254, 55188, 58254, 58254, 55188, + 55188, 55188, 55188, 55188, 55188, 24966, 27594, 26214, + 26214, 26214, 27594, 24966, 23831, 24385, 25575, 25575, + 25575, 25575, 24385, 23831, 15420, 15420, 16644, 16644, + 16644, 15420, 15420, 10923, 11398, 12193, 12193, 11398, + 10923, 10700, 10923, 11916, 10923, 10700, 5191, 5350, + 5350, 5191, 5041, 4810, 5041, 4520, 4520, 4263, +}; +static const int dv_weight_720_c[64] = { + 8192, 43691, 43691, 40330, 40330, 40330, 29127, 29127, + 29127, 29127, 29127, 29127, 27594, 29127, 29127, 27594, + 27594, 27594, 27594, 27594, 27594, 12483, 13797, 13107, + 13107, 13107, 13797, 12483, 11916, 12193, 12788, 12788, + 12788, 12788, 12193, 11916, 5761, 5761, 6242, 6242, + 6242, 5761, 5761, 5461, 5638, 5461, 6096, 5638, + 5461, 2661, 2745, 2962, 2745, 2661, 2583, 2661, + 2661, 2583, 2509, 2394, 2509, 2260, 2260, 2131, +}; + +/* the "inverse" DV100 weights are actually just the spec weights (zig-zagged) */ +static const int dv_iweight_1080_y[64] = { + 128, 16, 16, 17, 17, 17, 18, 18, + 18, 18, 18, 18, 19, 18, 18, 19, + 19, 19, 19, 19, 19, 42, 38, 40, + 40, 40, 38, 42, 44, 43, 41, 41, + 41, 41, 43, 44, 45, 45, 42, 42, + 42, 45, 45, 48, 46, 43, 43, 46, + 48, 49, 48, 44, 48, 49, 101, 98, + 98, 101, 104, 109, 104, 116, 116, 123, +}; +static const int dv_iweight_1080_c[64] = { + 128, 16, 16, 17, 17, 17, 25, 25, + 25, 25, 26, 25, 26, 25, 26, 26, + 26, 27, 27, 26, 26, 42, 38, 40, + 40, 40, 38, 42, 44, 43, 41, 41, + 41, 41, 43, 44, 91, 91, 84, 84, + 84, 91, 91, 96, 93, 86, 86, 93, + 96, 197, 191, 177, 191, 197, 203, 197, + 197, 203, 209, 219, 209, 232, 232, 246, +}; +static const int dv_iweight_720_y[64] = { + 128, 16, 16, 17, 17, 17, 18, 18, + 18, 18, 18, 18, 19, 18, 18, 19, + 19, 19, 19, 19, 19, 42, 38, 40, + 40, 40, 38, 42, 44, 43, 41, 41, + 41, 41, 43, 44, 68, 68, 63, 63, + 63, 68, 68, 96, 92, 86, 86, 92, + 96, 98, 96, 88, 96, 98, 202, 196, + 196, 202, 208, 218, 208, 232, 232, 246, +}; +static const int dv_iweight_720_c[64] = { + 128, 24, 24, 26, 26, 26, 36, 36, + 36, 36, 36, 36, 38, 36, 36, 38, + 38, 38, 38, 38, 38, 84, 76, 80, + 80, 80, 76, 84, 88, 86, 82, 82, + 82, 82, 86, 88, 182, 182, 168, 168, + 168, 182, 182, 192, 186, 192, 172, 186, + 192, 394, 382, 354, 382, 394, 406, 394, + 394, 406, 418, 438, 418, 464, 464, 492, +}; + + static const uint8_t dv_audio_shuffle525[10][9] = { { 0, 30, 60, 20, 50, 80, 10, 40, 70 }, /* 1st channel */ { 6, 36, 66, 26, 56, 86, 16, 46, 76 }, @@ -2544,8 +2745,24 @@ 48000, 44100, 32000, }; +static const uint8_t block_sizes_dv2550[8] = { + 112, 112, 112, 112, 80, 80, 0, 0, +}; + +static const uint8_t block_sizes_dv100[8] = { + 80, 80, 80, 80, 80, 80, 64, 64, +}; + +void find_macroblock_dv25_411(const struct DVprofile *sys, int channel, int seq, int av, int seg, int mbloc[10]); +void find_macroblock_dv25_420(const struct DVprofile *sys, int channel, int seq, int av, int seg, int mbloc[10]); +void find_macroblock_dv50(const struct DVprofile *sys, int channel, int seq, int av, int seg, int mbloc[10]); +void find_macroblock_dv100_1080i60(const struct DVprofile *sys, int channel, int seq, int av, int seg, int mbloc[10]); +void find_macroblock_dv100_1080i50(const struct DVprofile *sys, int channel, int seq, int av, int seg, int mbloc[10]); +void find_macroblock_dv100_720p60(const struct DVprofile *sys, int channel, int seq, int av, int seg, int mbloc[10]); + static const DVprofile dv_profiles[] = { { .dsf = 0, + .video_stype = 0x0, .frame_size = 120000, /* IEC 61834, SMPTE-314M - 525/60 (NTSC) */ .difseg_size = 10, .n_difchan = 1, @@ -2556,13 +2773,18 @@ .width = 720, .sar = {{10, 11}, {40, 33}}, .video_place = dv_place_411, + .find_macroblock = find_macroblock_dv25_411, .pix_fmt = PIX_FMT_YUV411P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .vs_total_ac_bits = (100 * 4 + 68*2) * 5, .audio_stride = 90, .audio_min_samples = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32Khz */ .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ .audio_shuffle = dv_audio_shuffle525, }, { .dsf = 1, + .video_stype = 0x0, .frame_size = 144000, /* IEC 61834 - 625/50 (PAL) */ .difseg_size = 12, .n_difchan = 1, @@ -2573,13 +2795,18 @@ .width = 720, .sar = {{59, 54}, {118, 81}}, .video_place = dv_place_420, + .find_macroblock = find_macroblock_dv25_420, .pix_fmt = PIX_FMT_YUV420P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .vs_total_ac_bits = (100 * 4 + 68*2) * 5, .audio_stride = 108, .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32Khz */ .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, .audio_shuffle = dv_audio_shuffle625, }, { .dsf = 1, + .video_stype = 0x0, .frame_size = 144000, /* SMPTE-314M - 625/50 (PAL) */ .difseg_size = 12, .n_difchan = 1, @@ -2590,13 +2817,18 @@ .width = 720, .sar = {{59, 54}, {118, 81}}, .video_place = dv_place_411P, + .find_macroblock = find_macroblock_dv25_411, .pix_fmt = PIX_FMT_YUV411P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .vs_total_ac_bits = (100 * 4 + 68*2) * 5, .audio_stride = 108, .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32Khz */ .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, .audio_shuffle = dv_audio_shuffle625, }, { .dsf = 0, + .video_stype = 0x4, .frame_size = 240000, /* SMPTE-314M - 525/60 (NTSC) 50 Mbps */ .difseg_size = 10, /* also known as "DVCPRO50" */ .n_difchan = 2, @@ -2607,13 +2839,18 @@ .width = 720, .sar = {{10, 11}, {40, 33}}, .video_place = dv_place_422_525, + .find_macroblock = find_macroblock_dv50, .pix_fmt = PIX_FMT_YUV422P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .vs_total_ac_bits = (100 * 4 + 68*2) * 5, .audio_stride = 90, .audio_min_samples = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32Khz */ .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ .audio_shuffle = dv_audio_shuffle525, }, { .dsf = 1, + .video_stype = 0x4, .frame_size = 288000, /* SMPTE-314M - 625/50 (PAL) 50 Mbps */ .difseg_size = 12, /* also known as "DVCPRO50" */ .n_difchan = 2, @@ -2624,12 +2861,82 @@ .width = 720, .sar = {{59, 54}, {118, 81}}, .video_place = dv_place_422_625, + .find_macroblock = find_macroblock_dv50, .pix_fmt = PIX_FMT_YUV422P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .vs_total_ac_bits = (100 * 4 + 68*2) * 5, .audio_stride = 108, .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32Khz */ .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, .audio_shuffle = dv_audio_shuffle625, - } + }, + { .dsf = 0, + .video_stype = 0x14, + .frame_size = 480000, /* SMPTE-370M - 1080i60 100 Mbps */ + .difseg_size = 10, /* also known as "DVCPRO HD" */ + .n_difchan = 4, + .frame_rate = 30000, + .ltc_divisor = 30, + .frame_rate_base = 1001, + .height = 1080, + .width = 1280, + .sar = {{1, 1}, {1, 1}}, + .video_place = 0, + .find_macroblock = find_macroblock_dv100_1080i60, + .pix_fmt = PIX_FMT_YUV422P, + .bpm = 8, + .block_sizes = block_sizes_dv100, + .vs_total_ac_bits = (68*6 + 52*2) * 5, + .audio_stride = 90, + .audio_min_samples = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32Khz */ + .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ + .audio_shuffle = dv_audio_shuffle525, + }, + { .dsf = 1, + .video_stype = 0x14, + .frame_size = 576000, /* SMPTE-370M - 1080i50 100 Mbps */ + .difseg_size = 12, /* also known as "DVCPRO HD" */ + .n_difchan = 4, + .frame_rate = 25, + .frame_rate_base = 1, + .ltc_divisor = 25, + .height = 1080, + .width = 1440, + .sar = {{1, 1}, {1, 1}}, + .video_place = 0, + .find_macroblock = find_macroblock_dv100_1080i50, + .pix_fmt = PIX_FMT_YUV422P, + .bpm = 8, + .block_sizes = block_sizes_dv100, + .vs_total_ac_bits = (68*6 + 52*2) * 5, + .audio_stride = 108, + .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32Khz */ + .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, + .audio_shuffle = dv_audio_shuffle625, + }, + { .dsf = 0, + .video_stype = 0x18, + .frame_size = 480000, /* SMPTE-370M - 720p60 100 Mbps */ + .difseg_size = 10, /* also known as "DVCPRO HD" */ + .n_difchan = 4, + .frame_rate = 30000, + .ltc_divisor = 30, + .frame_rate_base = 1001, + .height = 1440, + .width = 960, + .sar = {{1, 1}, {1, 1}}, + .video_place = 0, + .find_macroblock = find_macroblock_dv100_720p60, + .pix_fmt = PIX_FMT_YUV422P, + .bpm = 8, + .block_sizes = block_sizes_dv100, + .vs_total_ac_bits = (68*6 + 52*2) * 5, + .audio_stride = 90, + .audio_min_samples = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32Khz */ + .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ + .audio_shuffle = dv_audio_shuffle525, + }, }; enum dv_section_type { @@ -2642,7 +2949,7 @@ enum dv_pack_type { dv_header525 = 0x3f, /* see dv_write_pack for important details on */ - dv_header625 = 0xbf, /* these two packs */ + dv_header625 = 0xbf, /* these three packs */ dv_timecode = 0x13, dv_audio_source = 0x50, dv_audio_control = 0x51, @@ -2655,41 +2962,45 @@ dv_unknown_pack = 0xff, }; +#define DV_PROFILE_IS_HD(p) ((p)->video_stype & 0x10) +#define DV_PROFILE_IS_1080i50(p) (((p)->video_stype == 0x14) && ((p)->dsf == 1)) +#define DV_PROFILE_IS_1080i60(p) (((p)->video_stype == 0x14) && ((p)->dsf == 0)) + /* minimum number of bytes to read from a DV stream in order to determine the profile */ #define DV_PROFILE_BYTES (6*80) /* 6 DIF blocks */ -/* largest possible DV frame, in bytes (PAL 50Mbps) */ -#define DV_MAX_FRAME_SIZE 288000 +/* largest possible DV frame, in bytes (1080i50) */ +#define DV_MAX_FRAME_SIZE 576000 static inline const DVprofile* dv_frame_profile(uint8_t* frame) { - if ((frame[3] & 0x80) == 0) { /* DSF flag */ - /* it's an NTSC format */ - if ((frame[80*5 + 48 + 3] & 0x4) && (frame[80*5 + 48] == dv_video_source)) { /* 4:2:2 sampling */ - return &dv_profiles[3]; /* NTSC 50Mbps */ - } else { /* 4:1:1 sampling */ - return &dv_profiles[0]; /* NTSC 25Mbps */ - } - } else { - /* it's a PAL format */ - if ((frame[80*5 + 48 + 3] & 0x4) && (frame[80*5 + 48] == dv_video_source)) { /* 4:2:2 sampling */ - return &dv_profiles[4]; /* PAL 50Mbps */ - } else if ((frame[5] & 0x07) == 0) { /* APT flag */ - return &dv_profiles[1]; /* PAL 25Mbps 4:2:0 */ - } else - return &dv_profiles[2]; /* PAL 25Mbps 4:1:1 */ + int i; + + /* DSF flag */ + int dsf = (frame[3] & 0x80) >> 7; + + /* VAUX stype */ + int stype = frame[80*5 + 48 + 3] & 0x1f; + + /* 576i50 25Mbps 4:1:1 is a special case */ + if (dsf == 1 && stype == 0 && ((frame[5] & 0x07) != 0)) { + return &dv_profiles[2]; } + + for (i=0; iwidth != 720) - return NULL; - for (i=0; iheight == dv_profiles[i].height && codec->pix_fmt == dv_profiles[i].pix_fmt) + if (codec->height == dv_profiles[i].height && codec->pix_fmt == dv_profiles[i].pix_fmt && + codec->width == dv_profiles[i].width) return &dv_profiles[i]; return NULL; @@ -2698,15 +3009,18 @@ static inline int dv_write_dif_id(enum dv_section_type t, uint8_t chan_num, uint8_t seq_num, uint8_t dif_num, uint8_t* buf) { + int fsc = chan_num & 1; + int fsp = 1 - (chan_num >> 1); + buf[0] = (uint8_t)t; /* Section type */ buf[1] = (seq_num<<4) | /* DIF seq number 0-9 for 525/60; 0-11 for 625/50 */ - (chan_num << 3) | /* FSC: for 50Mb/s 0 - first channel; 1 - second */ - 7; /* reserved -- always 1 */ + (fsc << 3) | /* FSC: for 50 and 100Mb/s 0 - first channel; 1 - second */ + (fsp << 2) | /* FSP: for 100Mb/s 0 - channels 0-1; 1 - channels 2-3 */ + 3; /* reserved -- always 1 */ buf[2] = dif_num; /* DIF block number Video: 0-134, Audio: 0-8 */ return 3; } - static inline int dv_write_ssyb_id(uint8_t syb_num, uint8_t fr, uint8_t* buf) { if (syb_num == 0 || syb_num == 6) { Index: libavformat/dvenc.c =================================================================== --- libavformat/dvenc.c (revision 11056) +++ libavformat/dvenc.c (working copy) @@ -8,8 +8,9 @@ * Raw DV format * Copyright (c) 2002 Fabrice Bellard. * - * 50 Mbps (DVCPRO50) support - * Copyright (c) 2006 Daniel Maas + * 50 Mbps (DVCPRO50) and 100 Mbps (DVCPRO HD) support + * Copyright (c) 2006 Maas Digital LLC (Dan Maas, ) + * Funded by BBC Research & Development * * This file is part of FFmpeg. * @@ -28,23 +29,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include -#include #include "avformat.h" #include "dvdata.h" +#include "fifo.h" #include "dv.h" -#include "fifo.h" -struct DVMuxContext { - const DVprofile* sys; /* Current DV profile. E.g.: 525/60, 625/50 */ - int n_ast; /* Number of stereo audio streams (up to 2) */ - AVStream *ast[2]; /* Stereo audio streams */ - AVFifoBuffer audio_data[2]; /* Fifo for storing excessive amounts of PCM */ - int frames; /* Number of a current frame */ - time_t start_time; /* Start time of recording */ - int has_audio; /* frame under contruction has audio */ - int has_video; /* frame under contruction has video */ - uint8_t frame_buf[DV_MAX_FRAME_SIZE]; /* frame under contruction */ -}; +/* DJM - DVMuxContext moved to dv.h for use by fastencode */ +/* DJM - for fastencode */ +const DVprofile* dv_get_codec_profile(AVCodecContext *codec) { return dv_codec_profile(codec); } static const int dv_aaux_packs_dist[12][9] = { { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff }, @@ -67,13 +59,21 @@ sizeof(sys->audio_samples_dist[0]))]; } -static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* buf, ...) +static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* buf, int seq) { struct tm tc; time_t ct; int ltc_frame; - va_list ap; + /* Its hard to tell what SMPTE requires w.r.t. APT, but Quicktime needs it. + * We set it based on pix_fmt value but it really should be per DV profile */ + int apt; + if (DV_PROFILE_IS_HD(c->sys)) { + apt = 0; + } else { + apt = (c->sys->pix_fmt == PIX_FMT_YUV422P ? 1 : 0); + } + buf[0] = (uint8_t)pack_id; switch (pack_id) { case dv_timecode: @@ -101,25 +101,23 @@ (tc.tm_hour % 10); /* Units of hours */ break; case dv_audio_source: /* AAUX source pack */ - va_start(ap, buf); - buf[1] = (1 << 7) | /* locked mode -- SMPTE only supports locked mode */ + buf[1] = (0 << 7) | /* locked mode */ (1 << 6) | /* reserved -- always 1 */ (dv_audio_frame_size(c->sys, c->frames) - c->sys->audio_min_samples[0]); /* # of samples */ buf[2] = (0 << 7) | /* multi-stereo */ (0 << 5) | /* #of audio channels per block: 0 -- 1 channel */ - (0 << 4) | /* pair bit: 0 -- one pair of channels */ - !!va_arg(ap, int); /* audio mode */ + (1 << 4) | /* reserved */ + ((seq >= c->sys->difseg_size/2) ? 1 : 0); /* audio mode (1st or 2nd channel) */ buf[3] = (1 << 7) | /* res */ (1 << 6) | /* multi-language flag */ (c->sys->dsf << 5) | /* system: 60fields/50fields */ - (c->sys->n_difchan & 2); /* definition: 0 -- 25Mbps, 2 -- 50Mbps */ + (DV_PROFILE_IS_HD(c->sys) ? 0x3 : (apt<<1)); /* stype */ buf[4] = (1 << 7) | /* emphasis: 1 -- off */ (0 << 6) | /* emphasis time constant: 0 -- reserved */ (0 << 3) | /* frequency: 0 -- 48Khz, 1 -- 44,1Khz, 2 -- 32Khz */ 0; /* quantization: 0 -- 16bit linear, 1 -- 12bit nonlinear */ - va_end(ap); break; case dv_audio_control: buf[1] = (0 << 6) | /* copy protection: 0 -- unrestricted */ @@ -183,7 +181,7 @@ 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], i >= c->sys->difseg_size/2); + dv_write_pack(dv_aaux_packs_dist[i][j], c, &frame_ptr[3], i); 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) @@ -197,31 +195,55 @@ } } -static void dv_inject_metadata(DVMuxContext *c, uint8_t* frame) +/* DJM - exported for fastencode */ +void dv_inject_audio_raw(DVMuxContext *c, int channel, uint8_t* frame_ptr, uint8_t *data) { + 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], i); + 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] = data[of*2+1]; + frame_ptr[d+1] = data[of*2]; + } + frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */ + } + } +} + +void dv_inject_metadata(DVMuxContext *c, uint8_t* frame) +{ int j, k; uint8_t* buf; + int seq = 0; - for (buf = frame; buf < frame + c->sys->frame_size; buf += 150 * 80) { + for (buf = frame; buf < frame + c->sys->frame_size; buf += 150 * 80, seq++) { /* DV subcode: 2nd and 3d DIFs */ for (j = 80; j < 80 * 3; j += 80) { for (k = 6; k < 6 * 8; k += 8) - dv_write_pack(dv_timecode, c, &buf[j+k]); + dv_write_pack(dv_timecode, c, &buf[j+k], seq); if (((long)(buf-frame)/(c->sys->frame_size/(c->sys->difseg_size*c->sys->n_difchan))%c->sys->difseg_size) > 5) { /* FIXME: is this really needed ? */ - dv_write_pack(dv_video_recdate, c, &buf[j+14]); - dv_write_pack(dv_video_rectime, c, &buf[j+22]); - dv_write_pack(dv_video_recdate, c, &buf[j+38]); - dv_write_pack(dv_video_rectime, c, &buf[j+46]); + dv_write_pack(dv_video_recdate, c, &buf[j+14], seq); + dv_write_pack(dv_video_rectime, c, &buf[j+22], seq); + dv_write_pack(dv_video_recdate, c, &buf[j+38], seq); + dv_write_pack(dv_video_rectime, c, &buf[j+46], seq); } } /* DV VAUX: 4th, 5th and 6th 3DIFs */ for (j = 80*3 + 3; j < 80*6; j += 80) { - dv_write_pack(dv_video_recdate, c, &buf[j+5*2]); - dv_write_pack(dv_video_rectime, c, &buf[j+5*3]); - dv_write_pack(dv_video_recdate, c, &buf[j+5*11]); - dv_write_pack(dv_video_rectime, c, &buf[j+5*12]); + dv_write_pack(dv_video_recdate, c, &buf[j+5*2], seq); + dv_write_pack(dv_video_rectime, c, &buf[j+5*3], seq); + dv_write_pack(dv_video_recdate, c, &buf[j+5*11], seq); + dv_write_pack(dv_video_rectime, c, &buf[j+5*12], seq); } } } @@ -289,12 +311,12 @@ AVStream *vst = NULL; int i; - /* we support at most 1 video and 2 audio streams */ - if (s->nb_streams > 3) + /* we support at most 1 video and 4 audio streams */ + if (s->nb_streams > 5) return NULL; c->n_ast = 0; - c->ast[0] = c->ast[1] = NULL; + c->ast[0] = c->ast[1] = c->ast[2] = c->ast[3] = NULL; /* We have to sort out where audio and where video stream is */ for (i=0; inb_streams; i++) { @@ -325,8 +347,10 @@ if (!c->sys) goto bail_out; - if((c->n_ast > 1) && (c->sys->n_difchan < 2)) { + if(((c->n_ast > 1) && (c->sys->n_difchan < 2)) || + ((c->n_ast > 2) && (c->sys->n_difchan < 4))) { /* only 1 stereo pair is allowed in 25Mbps mode */ + /* only 2 stereo pairs allowed in 50Mbps mode */ goto bail_out; } @@ -365,8 +389,10 @@ if (!dv_init_mux(s)) { av_log(s, AV_LOG_ERROR, "Can't initialize DV format!\n" "Make sure that you supply exactly two streams:\n" - " video: 25fps or 29.97fps, audio: 2ch/48Khz/PCM\n" - " (50Mbps allows an optional second audio stream)\n"); + " video: 25fps or 29.97fps, YUV422P, YUV420P, or YUV411P\n" + " 720x576, 720x480, 1440x1080, 1280x1080, 960x1440\n" + " audio: 2ch/48Khz/PCM\n" + " (50Mbps allows an optional second audio stream, and 100Mbps allows up to four audio streams)\n"); return -1; } return 0; Index: libavformat/dv.c =================================================================== --- libavformat/dv.c (revision 11056) +++ libavformat/dv.c (working copy) @@ -8,8 +8,9 @@ * Raw DV format * Copyright (c) 2002 Fabrice Bellard. * - * 50 Mbps (DVCPRO50) support - * Copyright (c) 2006 Daniel Maas + * 50 Mbps (DVCPRO50) and 100 Mbps (DVCPRO HD) support + * Copyright (c) 2006 Maas Digital LLC (Dan Maas, ) + * Funded by BBC Research & Development * * This file is part of FFmpeg. * @@ -36,9 +37,9 @@ const DVprofile* sys; /* Current DV profile. E.g.: 525/60, 625/50 */ AVFormatContext* fctx; AVStream* vst; - AVStream* ast[2]; - AVPacket audio_pkt[2]; - uint8_t audio_buf[2][8192]; + AVStream* ast[4]; + AVPacket audio_pkt[4]; + uint8_t audio_buf[4][8192]; int ach; int frames; uint64_t abytes; @@ -98,12 +99,13 @@ * 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, +static int dv_extract_audio(uint8_t* frame, uint8_t *ppcm[4], const DVprofile *sys) { int size, chan, i, j, d, of, smpls, freq, quant, half_ch; uint16_t lc, rc; const uint8_t* as_pack; + uint8_t *pcm, ipcm; as_pack = dv_extract_pack(frame, dv_audio_source); if (!as_pack) /* No audio ? */ @@ -119,6 +121,9 @@ size = (sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */ half_ch = sys->difseg_size/2; + ipcm = 0; + pcm = ppcm[ipcm++]; + /* for each DIF channel */ for (chan = 0; chan < sys->n_difchan; chan++) { /* for each DIF segment */ @@ -126,10 +131,10 @@ 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; + assert(ipcm == 1); + pcm = ppcm[ipcm++]; + if (!pcm) + break; } /* for each AV sequence */ @@ -170,10 +175,10 @@ } } - /* next stereo channel (50Mbps only) */ - if(!pcm2) - break; - pcm = pcm2; + /* next stereo channel (50Mbps/100Mbps only) */ + pcm = ppcm[ipcm++]; + if (!pcm) + break; } return size; @@ -192,11 +197,17 @@ 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 */ + stype = (as_pack[3] & 0x1f); /* 0 - 2CH, 2 - 4CH, 3 - 8CH */ 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; + if (stype == 3) { + ach = 4; + } else if (stype == 2 || (quant && (freq == 2))) { + ach = 2; + } else { + ach = 1; + } /* Dynamic handling of the audio streams in DV */ for (i=0; isys = NULL; c->fctx = s; - c->ast[0] = c->ast[1] = NULL; + c->ast[0] = c->ast[1] = c->ast[2] = c->ast[3] = NULL; c->ach = 0; c->frames = 0; c->abytes = 0; @@ -310,6 +321,7 @@ uint8_t* buf, int buf_size) { int size, i; + uint8_t *ppcm[4]; if (buf_size < DV_PROFILE_BYTES || !(c->sys = dv_frame_profile(buf)) || @@ -320,11 +332,13 @@ /* Queueing audio packet */ /* FIXME: in case of no audio/bad audio we have to do something */ size = dv_extract_audio_info(c, buf); + ppcm[0] = ppcm[1] = ppcm[2] = ppcm[3] = NULL; for (i=0; iach; i++) { c->audio_pkt[i].size = size; c->audio_pkt[i].pts = c->abytes * 30000*8 / c->ast[i]->codec->bit_rate; + ppcm[i] = c->audio_buf[i]; } - dv_extract_audio(buf, c->audio_buf[0], c->audio_buf[1], c->sys); + dv_extract_audio(buf, ppcm, c->sys); c->abytes += size; /* Now it's time to return video packet */ @@ -363,9 +377,10 @@ c->frames= frame_offset; if (c->ach) c->abytes= av_rescale(c->frames, - c->ast[0]->codec->bit_rate * (int64_t)c->sys->frame_rate_base, - 8*c->sys->frame_rate); + c->ast[0]->codec->bit_rate * (int64_t)c->sys->frame_rate_base, + 8*c->sys->frame_rate); c->audio_pkt[0].size = c->audio_pkt[1].size = 0; + c->audio_pkt[2].size = c->audio_pkt[3].size = 0; } /************************************************************ @@ -391,6 +406,11 @@ return AVERROR(EIO); c->dv_demux->sys = dv_frame_profile(c->buf); + if(!c->dv_demux->sys) { + av_log(s, AV_LOG_ERROR, "Can't determine profile of DV input stream.\n"); + return -1; + } + s->bit_rate = av_rescale(c->dv_demux->sys->frame_size * 8, c->dv_demux->sys->frame_rate, c->dv_demux->sys->frame_rate_base); Index: libavformat/dv.h =================================================================== --- libavformat/dv.h (revision 11056) +++ libavformat/dv.h (working copy) @@ -29,6 +29,7 @@ #define FFMPEG_DV_H #include "avformat.h" +#include "fifo.h" typedef struct DVDemuxContext DVDemuxContext; DVDemuxContext* dv_init_demux(AVFormatContext* s); @@ -41,4 +42,29 @@ int dv_assemble_frame(DVMuxContext *c, AVStream*, const uint8_t*, int, uint8_t**); void dv_delete_mux(DVMuxContext*); +/* DJM - additional public exports for use by fastencode */ + +struct DVprofile; +const struct DVprofile* dv_get_codec_profile(AVCodecContext*); + +#ifndef DV_MAX_FRAME_SIZE +#define DV_MAX_FRAME_SIZE 576000 +#endif + +struct DVMuxContext { + const struct DVprofile* sys; /* Current DV profile. E.g.: 525/60, 625/50 */ + int n_ast; /* Number of stereo audio streams (up to 4) */ + AVStream *ast[4]; /* Stereo audio streams */ + AVFifoBuffer audio_data[4]; /* Fifo for storing excessive amounts of PCM */ + + int frames; /* Number of a current frame */ + time_t start_time; /* Start time of recording */ + int has_audio; /* frame under contruction has audio */ + int has_video; /* frame under contruction has video */ + uint8_t frame_buf[DV_MAX_FRAME_SIZE]; /* frame under contruction */ +}; + +void dv_inject_metadata(DVMuxContext *c, uint8_t* frame); +void dv_inject_audio_raw(DVMuxContext *c, int channel, uint8_t* frame_ptr, uint8_t *data); + #endif /* FFMPEG_DV_H */