Hi,
My colleagues and I are working on HEVC with alpha for Safari, according to Apple’s spec. We're focusing on how to create a proper mov container, for now. We're using the ES from a working HVEC with alpha sample, and tried to use ffmpeg's packager according to the spec, but the resulting mov doesn't play in Safari.
The elementary stream we're working with seems perfect with two interleaved streams: 1 VPS, 2 SPS, 2 PPS SEI.
We're having problems with the mov/mp4 container. Currently we're working on Apple's demo stream (puppets). We extracted the ES from the original mov and are trying to mux it back to mov via ffmpeg. With the changes below we made the resulting file, and can open and play it in Safari but without the video in the window (which already has the right size).
Here are the movs:
https://www.dropbox.com/sh/by054sfjoajl4hl/AAD6NtRG1GYRVFKuScycY_Oza?dl=0
The command is:
diff from ffmpeg master:
My colleagues and I are working on HEVC with alpha for Safari, according to Apple’s spec. We're focusing on how to create a proper mov container, for now. We're using the ES from a working HVEC with alpha sample, and tried to use ffmpeg's packager according to the spec, but the resulting mov doesn't play in Safari.
The elementary stream we're working with seems perfect with two interleaved streams: 1 VPS, 2 SPS, 2 PPS SEI.
We're having problems with the mov/mp4 container. Currently we're working on Apple's demo stream (puppets). We extracted the ES from the original mov and are trying to mux it back to mov via ffmpeg. With the changes below we made the resulting file, and can open and play it in Safari but without the video in the window (which already has the right size).
Here are the movs:
https://www.dropbox.com/sh/by054sfjoajl4hl/AAD6NtRG1GYRVFKuScycY_Oza?dl=0
The command is:
Code Block ./ffmpeg -i puppets_with_alpha_hevc.265 -c:v copy -tag:v hvc1 puppets_with_alpha_hevc2_tag.mov
diff from ffmpeg master:
Code Block diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c index 24658b3dfa..d2956a49a3 100644 --- a/libavcodec/h2645_parse.c + b/libavcodec/h2645_parse.c @@ -308,7 +308,7 @@ static int hevc_parse_nal_header(H2645NAL *nal, void *logctx) "nal_unit_type: %d(%s), nuh_layer_id: %d, temporal_id: %d\n", nal->type, hevc_nal_unit_name(nal->type), nuh_layer_id, nal->temporal_id); - return nuh_layer_id == 0; + return nuh_layer_id == 0 nuh_layer_id == 1; } static int h264_parse_nal_header(H2645NAL *nal, void *logctx) erangonen@Erans-MacBook-Pro ffmpeg % git diff libavcodec/hevc.c fatal: ambiguous argument 'libavcodec/hevc.c': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git <command> [<revision>...] -- [<file>...]' erangonen@Erans-MacBook-Pro ffmpeg % git diff libavformat/hevc.c diff --git a/libavformat/hevc.c b/libavformat/hevc.c index 3628d5a028..7a0eabbe5d 100644 --- a/libavformat/hevc.c + b/libavformat/hevc.c @@ -737,7 +737,7 @@ static int hvcc_array_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size, * for all other arrays. When the sample entry name is ‘hev1’, the default * value of array_completeness is 0 for all arrays. */ - if (nal_type == HEVC_NAL_VPS nal_type == HEVC_NAL_SPS nal_type == HEVC_NAL_PPS) + if (nal_type == HEVC_NAL_VPS nal_type == HEVC_NAL_SPS nal_type == HEVC_NAL_PPS nal_type == HEVC_NAL_SEI_PREFIX nal_type == HEVC_NAL_SEI_SUFFIX) array->array_completeness = ps_array_completeness; return 0; @@ -776,6 +776,8 @@ static int hvcc_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size, case HEVC_NAL_PPS: case HEVC_NAL_SEI_PREFIX: case HEVC_NAL_SEI_SUFFIX: + av_log(NULL, AV_LOG_WARNING, "got nal %d", nal_type); + ret = hvcc_array_add_nal_unit(nal_buf, nal_size, nal_type, ps_array_completeness, hvcc); if (ret < 0) @@ -836,7 +838,7 @@ static void hvcc_close(HEVCDecoderConfigurationRecord *hvcc) static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) { uint8_t i; - uint16_t j, vps_count = 0, sps_count = 0, pps_count = 0; + uint16_t j, vps_count = 0, sps_count = 0, pps_count = 0, sei_count = 0; /* * We only support writing HEVCDecoderConfigurationRecord version 1. @@ -926,10 +928,17 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) break; case HEVC_NAL_PPS: pps_count += hvcc->array[i].numNalus; + break; + case HEVC_NAL_SEI_PREFIX: + case HEVC_NAL_SEI_SUFFIX: + sei_count += hvcc->array[i].numNalus; break; default: break; } + + av_log(NULL, AV_LOG_WARNING, "vps_count:%d sps_count:%d pps_count:%d sei_count:%d", vps_count, sps_count, pps_count, sei_count); + if (!vps_count vps_count > HEVC_MAX_VPS_COUNT !sps_count sps_count > HEVC_MAX_SPS_COUNT !pps_count pps_count > HEVC_MAX_PPS_COUNT) @@ -1058,6 +1067,8 @@ int ff_hevc_annexb2mp4(AVIOContext *pb, const uint8_t *buf_in, case HEVC_NAL_VPS: case HEVC_NAL_SPS: case HEVC_NAL_PPS: + case HEVC_NAL_SEI_PREFIX: + case HEVC_NAL_SEI_SUFFIX: num_ps++; break; default: