[libav-devel] [PATCH 4/6] avcodec/h264_cabac: Fix CABAC+8x8dct in 4:4:4
From: Anton MitrofanovUse the correct ctxIdxInc calculation for coded_block_flag. Keep old behavior for old versions of x264 for backward compatibility. --- libavcodec/h264_cabac.c | 47 +-- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/libavcodec/h264_cabac.c b/libavcodec/h264_cabac.c index b28e486e52..c28f5680de 100644 --- a/libavcodec/h264_cabac.c +++ b/libavcodec/h264_cabac.c @@ -2329,21 +2329,40 @@ decode_intra_mb: if (CHROMA444(h) && IS_8x8DCT(mb_type)){ int i; uint8_t *nnz_cache = sl->non_zero_count_cache; -for (i = 0; i < 2; i++){ -if (sl->left_type[LEFT(i)] && !IS_8x8DCT(sl->left_type[LEFT(i)])) { -nnz_cache[3+8* 1 + 2*8*i]= -nnz_cache[3+8* 2 + 2*8*i]= -nnz_cache[3+8* 6 + 2*8*i]= -nnz_cache[3+8* 7 + 2*8*i]= -nnz_cache[3+8*11 + 2*8*i]= -nnz_cache[3+8*12 + 2*8*i]= IS_INTRA(mb_type) ? 64 : 0; +if (h->sei.unregistered.x264_build < 151U) { +for (i = 0; i < 2; i++){ +if (sl->left_type[LEFT(i)] && !IS_8x8DCT(sl->left_type[LEFT(i)])) { +nnz_cache[3+8* 1 + 2*8*i]= +nnz_cache[3+8* 2 + 2*8*i]= +nnz_cache[3+8* 6 + 2*8*i]= +nnz_cache[3+8* 7 + 2*8*i]= +nnz_cache[3+8*11 + 2*8*i]= +nnz_cache[3+8*12 + 2*8*i]= IS_INTRA(mb_type) ? 64 : 0; +} +} +if (sl->top_type && !IS_8x8DCT(sl->top_type)){ +uint32_t top_empty = !IS_INTRA(mb_type) ? 0 : 0x40404040; +AV_WN32A(_cache[4+8* 0], top_empty); +AV_WN32A(_cache[4+8* 5], top_empty); +AV_WN32A(_cache[4+8*10], top_empty); +} +} else { +for (i = 0; i < 2; i++){ +if (sl->left_type[LEFT(i)] && !IS_8x8DCT(sl->left_type[LEFT(i)])) { +nnz_cache[3+8* 1 + 2*8*i]= +nnz_cache[3+8* 2 + 2*8*i]= +nnz_cache[3+8* 6 + 2*8*i]= +nnz_cache[3+8* 7 + 2*8*i]= +nnz_cache[3+8*11 + 2*8*i]= +nnz_cache[3+8*12 + 2*8*i]= !IS_INTRA_PCM(sl->left_type[LEFT(i)]) ? 0 : 64; +} +} +if (sl->top_type && !IS_8x8DCT(sl->top_type)){ +uint32_t top_empty = !IS_INTRA_PCM(sl->top_type) ? 0 : 0x40404040; +AV_WN32A(_cache[4+8* 0], top_empty); +AV_WN32A(_cache[4+8* 5], top_empty); +AV_WN32A(_cache[4+8*10], top_empty); } -} -if (sl->top_type && !IS_8x8DCT(sl->top_type)){ -uint32_t top_empty = !IS_INTRA(mb_type) ? 0 : 0x40404040; -AV_WN32A(_cache[4+8* 0], top_empty); -AV_WN32A(_cache[4+8* 5], top_empty); -AV_WN32A(_cache[4+8*10], top_empty); } } h->cur_pic.mb_type[mb_xy] = mb_type; -- 2.13.1 ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
[libav-devel] [PATCH 5/6] avcodec/h264_mb: Fix 8x8dct in lossless for new versions of x264
From: Anton Mitrofanov--- libavcodec/h264_mb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264_mb.c b/libavcodec/h264_mb.c index da6a31d577..917c6aa3fc 100644 --- a/libavcodec/h264_mb.c +++ b/libavcodec/h264_mb.c @@ -636,7 +636,7 @@ static av_always_inline void hl_decode_mb_predict_luma(const H264Context *h, uint8_t *const ptr = dest_y + block_offset[i]; const int dir = sl->intra4x4_pred_mode_cache[scan8[i]]; if (transform_bypass && h->ps.sps->profile_idc == 244 && dir <= 1) { -if (h->sei.unregistered.x264_build != -1) { +if (h->sei.unregistered.x264_build < 151U) { h->hpc.pred8x8l_add[dir](ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize); } else h->hpc.pred8x8l_filter_add[dir](ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), -- 2.13.1 ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
[libav-devel] [PATCH 3/6] avcodec/h264: fix Lossless Decoding (Profile 244) for 8x8 Intra Prediction
From: Yogender Kumar GuptaThis is limited to the case where x264_build = -1, to not break x264 decoding Signed-off-by: Michael Niedermayer --- libavcodec/h264_mb.c | 7 +++- libavcodec/h264pred.c | 2 ++ libavcodec/h264pred.h | 2 ++ libavcodec/h264pred_template.c | 73 ++ 4 files changed, 83 insertions(+), 1 deletion(-) diff --git a/libavcodec/h264_mb.c b/libavcodec/h264_mb.c index f037bd5163..da6a31d577 100644 --- a/libavcodec/h264_mb.c +++ b/libavcodec/h264_mb.c @@ -636,7 +636,12 @@ static av_always_inline void hl_decode_mb_predict_luma(const H264Context *h, uint8_t *const ptr = dest_y + block_offset[i]; const int dir = sl->intra4x4_pred_mode_cache[scan8[i]]; if (transform_bypass && h->ps.sps->profile_idc == 244 && dir <= 1) { -h->hpc.pred8x8l_add[dir](ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize); +if (h->sei.unregistered.x264_build != -1) { +h->hpc.pred8x8l_add[dir](ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize); +} else +h->hpc.pred8x8l_filter_add[dir](ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), +(sl-> topleft_samples_available << i) & 0x8000, + (sl->topright_samples_available << i) & 0x4000, linesize); } else { const int nnz = sl->non_zero_count_cache[scan8[i + p * 16]]; h->hpc.pred8x8l[dir](ptr, (sl->topleft_samples_available << i) & 0x8000, diff --git a/libavcodec/h264pred.c b/libavcodec/h264pred.c index 7627eb076d..135babcab4 100644 --- a/libavcodec/h264pred.c +++ b/libavcodec/h264pred.c @@ -552,6 +552,8 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred4x4_add [ HOR_PRED ]= FUNCC(pred4x4_horizontal_add , depth);\ h->pred8x8l_add [VERT_PRED ]= FUNCC(pred8x8l_vertical_add , depth);\ h->pred8x8l_add [ HOR_PRED ]= FUNCC(pred8x8l_horizontal_add , depth);\ +h->pred8x8l_filter_add [VERT_PRED ]= FUNCC(pred8x8l_vertical_filter_add , depth);\ +h->pred8x8l_filter_add [ HOR_PRED ]= FUNCC(pred8x8l_horizontal_filter_add , depth);\ if (chroma_format_idc <= 1) {\ h->pred8x8_add [VERT_PRED8x8]= FUNCC(pred8x8_vertical_add, depth);\ h->pred8x8_add [ HOR_PRED8x8]= FUNCC(pred8x8_horizontal_add , depth);\ diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h index 60e74349c9..6e495f9fc6 100644 --- a/libavcodec/h264pred.h +++ b/libavcodec/h264pred.h @@ -101,6 +101,8 @@ typedef struct H264PredContext { int16_t *block /*align 16*/, ptrdiff_t stride); void(*pred8x8l_add[2])(uint8_t *pix /*align 8*/, int16_t *block /*align 16*/, ptrdiff_t stride); +void(*pred8x8l_filter_add[2])(uint8_t *pix /*align 8*/, + int16_t *block /*align 16*/, int topleft, int topright, ptrdiff_t stride); void(*pred8x8_add[3])(uint8_t *pix /*align 8*/, const int *block_offset, int16_t *block /*align 16*/, ptrdiff_t stride); diff --git a/libavcodec/h264pred_template.c b/libavcodec/h264pred_template.c index 8492b2b0a2..42ff350b4c 100644 --- a/libavcodec/h264pred_template.c +++ b/libavcodec/h264pred_template.c @@ -1123,6 +1123,79 @@ static void FUNCC(pred8x8l_horizontal_up)(uint8_t *_src, int has_topleft, SRC(5,6)=SRC(5,7)=SRC(6,4)=SRC(6,5)=SRC(6,6)= SRC(6,7)=SRC(7,4)=SRC(7,5)=SRC(7,6)=SRC(7,7)= l7; } + +static void FUNCC(pred8x8l_vertical_filter_add)(uint8_t *_src, int16_t *_block, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ +int i; +pixel *src = (pixel*)_src; +const dctcoef *block = (const dctcoef*)_block; +pixel pix[8]; +int stride = _stride/sizeof(pixel); +PREDICT_8x8_LOAD_TOP; + +pix[0] = t0; +pix[1] = t1; +pix[2] = t2; +pix[3] = t3; +pix[4] = t4; +pix[5] = t5; +pix[6] = t6; +pix[7] = t7; + +for(i=0; i<8; i++){ +pixel v = pix[i]; +src[0*stride]= v += block[0]; +src[1*stride]= v += block[8]; +src[2*stride]= v += block[16]; +src[3*stride]= v += block[24]; +src[4*stride]= v += block[32]; +src[5*stride]= v += block[40]; +src[6*stride]= v += block[48]; +src[7*stride]= v + block[56]; +src++; +block++; +} + +memset(_block, 0, sizeof(dctcoef) * 64); +} + +static void FUNCC(pred8x8l_horizontal_filter_add)(uint8_t *_src, int16_t *_block, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ +int i; +pixel
[libav-devel] [PATCH 1/6] avcodec/h264_slice: Also copy x264_build in ff_h264_update_thread_context()
From: Michael NiedermayerFixes fate-h264-lossless Signed-off-by: Michael Niedermayer --- libavcodec/h264_slice.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index c9f1dbb86f..0ce4127a1d 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -408,6 +408,7 @@ int ff_h264_update_thread_context(AVCodecContext *dst, // extradata/NAL handling h->is_avc = h1->is_avc; h->nal_length_size = h1->nal_length_size; +h->sei.unregistered.x264_build = h1->sei.unregistered.x264_build; memcpy(>poc,>poc,sizeof(h->poc)); -- 2.13.1 ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
[libav-devel] [PATCH 2/6] avcodec/h264: Don't reset the x264 build info once read
From: Anton MitrofanovIn order to fix fate-h264-lossless (change by Hendrik) --- libavcodec/h264_sei.c | 1 - libavcodec/h264dec.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c index 3ca2b7a6cd..a2151bfaf6 100644 --- a/libavcodec/h264_sei.c +++ b/libavcodec/h264_sei.c @@ -38,7 +38,6 @@ static const uint8_t sei_num_clock_ts_table[9] = { void ff_h264_sei_uninit(H264SEIContext *h) { -h->unregistered.x264_build = -1; h->recovery_point.recovery_frame_cnt = -1; h->picture_timing.dpb_output_delay = 0; diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 2a532a7ef7..c81510fc05 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -294,6 +294,7 @@ static int h264_init_context(AVCodecContext *avctx, H264Context *h) h->poc.prev_poc_msb = 1 << 16; h->recovery_frame= -1; h->frame_recovered = 0; +h->sei.unregistered.x264_build = -1; h->next_outputed_poc = INT_MIN; for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) -- 2.13.1 ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
[libav-devel] [PATCH 6/6] avcodec/h264: Fix mix of lossless and lossy MBs decoding
From: Anton Mitrofanov--- libavcodec/h264_cabac.c | 16 libavcodec/h264_cavlc.c | 16 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/libavcodec/h264_cabac.c b/libavcodec/h264_cabac.c index c28f5680de..e6dc5258a4 100644 --- a/libavcodec/h264_cabac.c +++ b/libavcodec/h264_cabac.c @@ -2371,14 +2371,6 @@ decode_intra_mb: const uint8_t *scan, *scan8x8; const uint32_t *qmul; -if(IS_INTERLACED(mb_type)){ -scan8x8 = sl->qscale ? h->field_scan8x8 : h->field_scan8x8_q0; -scan= sl->qscale ? h->field_scan : h->field_scan_q0; -}else{ -scan8x8 = sl->qscale ? h->zigzag_scan8x8 : h->zigzag_scan8x8_q0; -scan= sl->qscale ? h->zigzag_scan : h->zigzag_scan_q0; -} - // decode_cabac_mb_dqp if(get_cabac_noinline( >cabac, >cabac_state[60 + (sl->last_qscale_diff != 0)])){ int val = 1; @@ -2409,6 +2401,14 @@ decode_intra_mb: }else sl->last_qscale_diff=0; +if(IS_INTERLACED(mb_type)){ +scan8x8 = sl->qscale ? h->field_scan8x8 : h->field_scan8x8_q0; +scan= sl->qscale ? h->field_scan : h->field_scan_q0; +}else{ +scan8x8 = sl->qscale ? h->zigzag_scan8x8 : h->zigzag_scan8x8_q0; +scan= sl->qscale ? h->zigzag_scan : h->zigzag_scan_q0; +} + decode_cabac_luma_residual(h, sl, scan, scan8x8, pixel_shift, mb_type, cbp, 0); if (CHROMA444(h)) { decode_cabac_luma_residual(h, sl, scan, scan8x8, pixel_shift, mb_type, cbp, 1); diff --git a/libavcodec/h264_cavlc.c b/libavcodec/h264_cavlc.c index c11e211bd8..d57062bc56 100644 --- a/libavcodec/h264_cavlc.c +++ b/libavcodec/h264_cavlc.c @@ -1093,14 +1093,6 @@ decode_intra_mb: const uint8_t *scan, *scan8x8; const int max_qp = 51 + 6 * (h->ps.sps->bit_depth_luma - 8); -if(IS_INTERLACED(mb_type)){ -scan8x8 = sl->qscale ? h->field_scan8x8_cavlc : h->field_scan8x8_cavlc_q0; -scan= sl->qscale ? h->field_scan : h->field_scan_q0; -}else{ -scan8x8 = sl->qscale ? h->zigzag_scan8x8_cavlc : h->zigzag_scan8x8_cavlc_q0; -scan= sl->qscale ? h->zigzag_scan : h->zigzag_scan_q0; -} - dquant= get_se_golomb(>gb); sl->qscale += dquant; @@ -1117,6 +1109,14 @@ decode_intra_mb: sl->chroma_qp[0] = get_chroma_qp(h->ps.pps, 0, sl->qscale); sl->chroma_qp[1] = get_chroma_qp(h->ps.pps, 1, sl->qscale); +if(IS_INTERLACED(mb_type)){ +scan8x8 = sl->qscale ? h->field_scan8x8_cavlc : h->field_scan8x8_cavlc_q0; +scan= sl->qscale ? h->field_scan : h->field_scan_q0; +}else{ +scan8x8 = sl->qscale ? h->zigzag_scan8x8_cavlc : h->zigzag_scan8x8_cavlc_q0; +scan= sl->qscale ? h->zigzag_scan : h->zigzag_scan_q0; +} + if ((ret = decode_luma_residual(h, sl, gb, scan, scan8x8, pixel_shift, mb_type, cbp, 0)) < 0 ) { return -1; } -- 2.13.1 ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
[libav-devel] [PATCH 1/4] movenc: use correct tag list for AVOutputFormat.codec_tag
ff_mp4_obj_type contains the wrong type of tags for AVOutputFormat.codec_tag. AVOutputFormat.codec_tag is used to validate AVCodecParameters.codec_tag so needs to be the same type of tag. Creates new tag lists for mp4 and ismv. New tag lists support same list of codecs found in ff_mp4_obj_type. psp uses the same tag list as mp4 since these both use mp4_get_codec_tag to look up tags. --- libavformat/movenc.c | 37 ++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index e389029..6c3d36c 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -,6 +,36 @@ error: return res; } +const AVCodecTag codec_mp4_tags[] = { +{ AV_CODEC_ID_MOV_TEXT, MKTAG('t', 'x', '3', 'g') }, +{ AV_CODEC_ID_MPEG4 , MKTAG('m', 'p', '4', 'v') }, +{ AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, +{ AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') }, +{ AV_CODEC_ID_AAC , MKTAG('m', 'p', '4', 'a') }, +{ AV_CODEC_ID_MP4ALS , MKTAG('m', 'p', '4', 'a') }, +{ AV_CODEC_ID_MPEG2VIDEO , MKTAG('m', 'p', '4', 'v') }, +{ AV_CODEC_ID_MP3 , MKTAG('m', 'p', '4', 'a') }, +{ AV_CODEC_ID_MP2 , MKTAG('m', 'p', '4', 'a') }, +{ AV_CODEC_ID_MPEG1VIDEO , MKTAG('m', 'p', '4', 'v') }, +{ AV_CODEC_ID_MJPEG , MKTAG('m', 'p', '4', 'v') }, +{ AV_CODEC_ID_PNG , MKTAG('m', 'p', '4', 'v') }, +{ AV_CODEC_ID_JPEG2000, MKTAG('m', 'p', '4', 'v') }, +{ AV_CODEC_ID_VC1 , MKTAG('v', 'c', '-', '1') }, +{ AV_CODEC_ID_DIRAC , MKTAG('d', 'r', 'a', 'c') }, +{ AV_CODEC_ID_AC3 , MKTAG('a', 'c', '-', '3') }, +{ AV_CODEC_ID_DTS , MKTAG('m', 'p', '4', 'a') }, +{ AV_CODEC_ID_TSCC2 , MKTAG('m', 'p', '4', 'v') }, +{ AV_CODEC_ID_VORBIS , MKTAG('m', 'p', '4', 'a') }, +{ AV_CODEC_ID_DVD_SUBTITLE, MKTAG('m', 'p', '4', 's') }, +{ AV_CODEC_ID_QCELP , MKTAG('m', 'p', '4', 'a') }, +{ AV_CODEC_ID_NONE,0 }, +}; + +const AVCodecTag codec_ism_tags[] = { +{ AV_CODEC_ID_WMAPRO , MKTAG('w', 'm', 'a', ' ') }, +{ AV_CODEC_ID_NONE,0 }, +}; + #if CONFIG_MOV_MUXER MOV_CLASS(mov) AVOutputFormat ff_mov_muxer = { @@ -4496,7 +4526,7 @@ AVOutputFormat ff_mp4_muxer = { .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, -.codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, +.codec_tag = (const AVCodecTag* const []){ codec_mp4_tags, 0 }, .priv_class= _muxer_class, }; #endif @@ -4514,7 +4544,7 @@ AVOutputFormat ff_psp_muxer = { .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, -.codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, +.codec_tag = (const AVCodecTag* const []){ codec_mp4_tags, 0 }, .priv_class= _muxer_class, }; #endif @@ -4567,7 +4597,8 @@ AVOutputFormat ff_ismv_muxer = { .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, -.codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, +.codec_tag = (const AVCodecTag* const []){ +codec_mp4_tags, codec_ism_tags, 0 }, .priv_class= _muxer_class, }; #endif -- 2.9.4 ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
[libav-devel] [PATCH 3/4] movenc: write correct format hvcc when tag is hvc1
--- libavformat/movenc.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index eb12431..0c1508f 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -727,7 +727,10 @@ static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, 0); ffio_wfourcc(pb, "hvcC"); -ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0); +if (track->tag == MKTAG('h','v','c','1')) +ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 1); +else +ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0); return update_size(pb, pos); } -- 2.9.4 ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
[libav-devel] [PATCH 4/4] movenc: allow alternative hvc1 h.265 codec tag
If AVCodecParameters.codec_tag is 'hvc1' use it instead of 'hev1' for h.265 streams. QuickTime (and other Apple software) requires 'hvc1'. --- libavformat/movenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 0c1508f..2ff4270 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -4435,6 +4435,7 @@ const AVCodecTag codec_mp4_tags[] = { { AV_CODEC_ID_MPEG4 , MKTAG('m', 'p', '4', 'v') }, { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, { AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') }, +{ AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') }, { AV_CODEC_ID_AAC , MKTAG('m', 'p', '4', 'a') }, { AV_CODEC_ID_MP4ALS , MKTAG('m', 'p', '4', 'a') }, { AV_CODEC_ID_MPEG2VIDEO , MKTAG('m', 'p', '4', 'v') }, -- 2.9.4 ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
[libav-devel] [PATCH 2/4] movenc: generalize codec_tag lookup code
This simplifies the code and adds the capability to support alternative tags for the same codec_id --- libavformat/movenc.c | 137 ++- 1 file changed, 70 insertions(+), 67 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 6c3d36c..eb12431 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -32,6 +32,7 @@ #include "isom.h" #include "avc.h" +#include "libavcodec/internal.h" #include "libavcodec/bitstream.h" #include "libavcodec/put_bits.h" #include "libavcodec/vc1_common.h" @@ -778,50 +779,39 @@ static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track) return 0; } -static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track) +static int validate_codec_tag(const AVCodecTag * const tags[], unsigned int tag, + enum AVCodecID id) { -int tag = track->par->codec_tag; - -if (!ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id)) -return 0; +const AVCodecTag *avctag; +int n; -if (track->par->codec_id == AV_CODEC_ID_H264) tag = MKTAG('a','v','c','1'); -else if (track->par->codec_id == AV_CODEC_ID_HEVC) tag = MKTAG('h','e','v','1'); -else if (track->par->codec_id == AV_CODEC_ID_AC3) tag = MKTAG('a','c','-','3'); -else if (track->par->codec_id == AV_CODEC_ID_DIRAC) tag = MKTAG('d','r','a','c'); -else if (track->par->codec_id == AV_CODEC_ID_MOV_TEXT) tag = MKTAG('t','x','3','g'); -else if (track->par->codec_id == AV_CODEC_ID_VC1) tag = MKTAG('v','c','-','1'); -else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) tag = MKTAG('m','p','4','v'); -else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) tag = MKTAG('m','p','4','a'); -else if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE) tag = MKTAG('m','p','4','s'); - -return tag; +for (n = 0; tags[n]; n++) { +avctag = tags[n]; +while (avctag->id != AV_CODEC_ID_NONE) { +if (avpriv_toupper4(avctag->tag) == avpriv_toupper4(tag) && +avctag->id == id) +return 1; +avctag++; +} +} +return 0; } -static const AVCodecTag codec_ipod_tags[] = { -{ AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, -{ AV_CODEC_ID_MPEG4,MKTAG('m','p','4','v') }, -{ AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, -{ AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') }, -{ AV_CODEC_ID_AC3, MKTAG('a','c','-','3') }, -{ AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, -{ AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') }, -{ AV_CODEC_ID_NONE, 0 }, -}; - -static int ipod_get_codec_tag(AVFormatContext *s, MOVTrack *track) +static int get_codec_tag(AVFormatContext *s, MOVTrack *track) { int tag = track->par->codec_tag; -// keep original tag for subs, ipod supports both formats -if (!(track->par->codec_type == AVMEDIA_TYPE_SUBTITLE && - (tag == MKTAG('t', 'x', '3', 'g') || - tag == MKTAG('t', 'e', 'x', 't' -tag = ff_codec_get_tag(codec_ipod_tags, track->par->codec_id); - -if (!av_match_ext(s->filename, "m4a") && !av_match_ext(s->filename, "m4v")) -av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v " - "Quicktime/Ipod might not play the file\n"); +if (!tag || (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL && + s->oformat->codec_tag && + !validate_codec_tag(s->oformat->codec_tag, tag, + track->par->codec_id))) { +int n = 0; + +tag = 0; +while (!tag && s->oformat->codec_tag[n]) +tag = ff_codec_get_tag(s->oformat->codec_tag[n++], + track->par->codec_id); +} return tag; } @@ -926,42 +916,24 @@ static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track) return tag; } -static const AVCodecTag codec_3gp_tags[] = { -{ AV_CODEC_ID_H263, MKTAG('s','2','6','3') }, -{ AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, -{ AV_CODEC_ID_MPEG4,MKTAG('m','p','4','v') }, -{ AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, -{ AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') }, -{ AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') }, -{ AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, -{ AV_CODEC_ID_NONE, 0 }, -}; - -static const AVCodecTag codec_f4v_tags[] = { -{ AV_CODEC_ID_MP3,MKTAG('.','m','p','3') }, -{ AV_CODEC_ID_AAC,MKTAG('m','p','4','a') }, -{ AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, -{ AV_CODEC_ID_VP6A, MKTAG('V','P','6','A') }, -{ AV_CODEC_ID_VP6F, MKTAG('V','P','6','F') }, -{ AV_CODEC_ID_NONE, 0 }, -}; - static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track) { int tag; if (track->mode == MODE_MP4 || track->mode == MODE_PSP) -tag = mp4_get_codec_tag(s, track); -else if (track->mode ==
Re: [libav-devel] [PATCH] movenc: Allow use of hvc1 tag for h.265
On Wed, 14 Jun 2017, John Stebbins wrote: On 06/14/2017 01:06 PM, Martin Storsjö wrote: On Wed, 14 Jun 2017, John Stebbins wrote: On 06/14/2017 12:13 PM, Martin Storsjö wrote: On Wed, 14 Jun 2017, John Stebbins wrote: On 06/13/2017 11:16 PM, Martin Storsjö wrote: On Tue, 13 Jun 2017, John Stebbins wrote: On 06/13/2017 12:13 PM, Martin Storsjö wrote: On Mon, 12 Jun 2017, John Stebbins wrote: If AVCodecParameters.codec_tag is 'hvc1' use it instead of 'hev1' for h.265 streams. QuickTime (and other Apple software) requires 'hvc1'. --- libavformat/movenc.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index e389029..8d89a7a 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -726,7 +726,10 @@ static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, 0); ffio_wfourcc(pb, "hvcC"); -ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0); +if (track->tag == MKTAG('h','v','c','1')) +ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 1); +else +ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0); return update_size(pb, pos); } @@ -786,6 +789,8 @@ static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track) return 0; if (track->par->codec_id == AV_CODEC_ID_H264) tag = MKTAG('a','v','c','1'); +else if (track->par->codec_id == AV_CODEC_ID_HEVC && + tag == MKTAG('h','v','c','1')) ; else if (track->par->codec_id == AV_CODEC_ID_HEVC) tag = MKTAG('h','e','v','1'); else if (track->par->codec_id == AV_CODEC_ID_AC3) tag = MKTAG('a','c','-','3'); else if (track->par->codec_id == AV_CODEC_ID_DIRAC) tag = MKTAG('d','r','a','c'); @@ -4496,7 +4501,9 @@ AVOutputFormat ff_mp4_muxer = { .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, -.codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, +.codec_tag = (const AVCodecTag* const []){ +ff_codec_movvideo_tags, ff_codec_movaudio_tags, +ff_codec_movsubtitle_tags, 0 }, .priv_class= _muxer_class, I guess this change is because libavformat refuses to allow you to set a custom codec_tag unless it is found in the codec_tag list, right? Does this have any other practical implications? I feel a little uneasy about this part of it... Yes, this change was to fix result of validate_codec_tag in mux.c. I was curious about this myself. I could only find 2 places that this codec_tag array is used. One in validate_codec_tag which is the instance that needed fixing, and another in avconv where it is checking if the source codec_tag is valid for the output format when doing stream copy. In both of these cases ff_mp4_obj_type is wrong for codec_tag so I'm not sure why this was used in the first place. According to git history, this was used from the beginning, but makes no sense. I also looked at who calls validate_codec_tag just to be sure it's being used consistently. It's only used by avformat_write_header. I also ran fate to check for regressions. Ok, that makes sense. In that case though, I would very much prefer to do this in two separate steps; one that removes the .codec_tag part from the AVOutputFormat, with a thorough explanation of this (pretty much what you just wrote) and saying that this will allow the caller to indicate that actual codec tag he wants to be used, and then this one on top that allows you to use hvc1. Ok, I'll do that. There are 2 additional places ff_mp4_obj_type is used for codec_tag. psp and ismv also use it. Should I just do the same thing to them, or would you rather something more tailored for those use cases (as it is done for ipod)? I don't happen to know what fourcc are permitted in these variants. There's nothing in the code that currently limits what can be put in these. Hmm, after removing codec_tag in this case, what happens if you try to mux an unsupported codec? Would it be even better to use another list like the current one, but which contains the actual real tags that can end up written in the mp4 file, so you can have both HEVC alternatives in there? I think you misread something. I didn't "remove" codec_tag. I set it to { ff_codec_movvideo_tags, ff_codec_movaudio_tags, ff_codec_movsubtitle_tags, 0 } Yep, and now on a second thought I think that's wrong. Wouldn't that allow you to (attempt to) mux codecs which really aren't supposed to go into an mp4, say SVQ3? So instead it'd be better to mirror the actual list of codecs that are allowed in mp4, that currently are in ff_mp4_obj_type, but with sensible tag names (including both hev1 and hvc1)? Understood. I assumed mov and mp4 allowed pretty much the same stream types. But I see this is incorrect. I'll roll that