[PATCH 0/2] MR10468: winedmo: Call avformat_find_stream_info for H264 streams missing aspect ratio.
Supersedes https://gitlab.winehq.org/wine/wine/-/merge_requests/10321, without the Wine / winedmo specific registry checks in the tests. We generally don't do that, the tests should just pass with the default backend selection and we will update them whenever the default is switched. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10468
From: Yuxuan Shui <yshui@codeweavers.com> --- dlls/mfsrcsnk/tests/mfsrcsnk.c | 83 +++++++++++++++++++++++++ dlls/mfsrcsnk/tests/resource.rc | 15 +++++ dlls/mfsrcsnk/tests/test_metadata.mp4 | Bin 0 -> 1832 bytes dlls/mfsrcsnk/tests/test_metadata2.mp4 | Bin 0 -> 1848 bytes 4 files changed, 98 insertions(+) create mode 100644 dlls/mfsrcsnk/tests/test_metadata.mp4 create mode 100644 dlls/mfsrcsnk/tests/test_metadata2.mp4 diff --git a/dlls/mfsrcsnk/tests/mfsrcsnk.c b/dlls/mfsrcsnk/tests/mfsrcsnk.c index cc7b090d074..af44a074ea7 100644 --- a/dlls/mfsrcsnk/tests/mfsrcsnk.c +++ b/dlls/mfsrcsnk/tests/mfsrcsnk.c @@ -831,6 +831,88 @@ static void test_thinning(void) IMFMediaSource_Release(source); } +static void test_mp4_extra_metadata(void) +{ + IMFPresentationDescriptor *presentation_descriptor; + IMFStreamDescriptor *stream_descriptor; + IMFMediaTypeHandler *type_handler; + IMFMediaType *media_type; + IMFMediaSource *source; + IMFByteStream *stream; + DWORD stream_count; + UINT64 value64; + BOOL selected; + HRESULT hr; + + /* Some metadata are duplicated at multiple levels in a mp4. Notably, the pixel aspect ratio + * is defined in both: 1) the pasp atom, and 2) the avcC atom. + * This test checks how they are treated by the byte stream handler. For example: are they both + * parsed? Which one takes precedence if both are present? */ + + /* 1. has no pasp atom. Aspect ratio set to 3:4 in the SPS contained by the avcC atom. */ + stream = create_resource_byte_stream(L"test_metadata.mp4"); + hr = create_source(&CLSID_MPEG4ByteStreamHandlerPlugin, stream, &source); + IMFByteStream_Release(stream); + + if (FAILED(hr)) + { + win_skip("Failed to create MPEG4 source: %#lx.\n", hr); + return; + } + + hr = IMFMediaSource_CreatePresentationDescriptor(source, &presentation_descriptor); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFPresentationDescriptor_GetStreamDescriptorCount(presentation_descriptor, &stream_count); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(stream_count == 1, "Unexpected stream count %lu.\n", stream_count); + hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(presentation_descriptor, 0, &selected, &stream_descriptor); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFStreamDescriptor_GetMediaTypeHandler(stream_descriptor, &type_handler); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + value64 = 0xdeadbeef; + hr = IMFMediaType_GetUINT64(media_type, &MF_MT_PIXEL_ASPECT_RATIO, &value64); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(value64 == 0x300000004, "Unexpected aspect ratio %#I64x.\n", value64); + IMFMediaType_Release(media_type); + IMFMediaTypeHandler_Release(type_handler); + IMFStreamDescriptor_Release(stream_descriptor); + IMFPresentationDescriptor_Release(presentation_descriptor); + hr = IMFMediaSource_Shutdown(source); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaSource_Release(source); + + /* 2. has pasp atom. Aspect ratio set to 3:4 in the SPS, and 15:16 in the pasp. */ + stream = create_resource_byte_stream(L"test_metadata2.mp4"); + hr = create_source(&CLSID_MPEG4ByteStreamHandlerPlugin, stream, &source); + IMFByteStream_Release(stream); + + hr = IMFMediaSource_CreatePresentationDescriptor(source, &presentation_descriptor); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFPresentationDescriptor_GetStreamDescriptorCount(presentation_descriptor, &stream_count); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(stream_count == 1, "Unexpected stream count %lu.\n", stream_count); + hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(presentation_descriptor, 0, &selected, &stream_descriptor); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFStreamDescriptor_GetMediaTypeHandler(stream_descriptor, &type_handler); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + value64 = 0xdeadbeef; + hr = IMFMediaType_GetUINT64(media_type, &MF_MT_PIXEL_ASPECT_RATIO, &value64); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + /* pasp takes precedence */ + todo_wine ok(value64 == 0xf00000010, "Unexpected aspect ratio: %#I64x.\n", value64); + IMFMediaType_Release(media_type); + IMFMediaTypeHandler_Release(type_handler); + IMFStreamDescriptor_Release(stream_descriptor); + IMFPresentationDescriptor_Release(presentation_descriptor); + hr = IMFMediaSource_Shutdown(source); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaSource_Release(source); +} + static void test_end_of_presentation(void) { IMFPresentationDescriptor *pd; @@ -960,6 +1042,7 @@ START_TEST(mfsrcsnk) test_wave_sink(); test_thinning(); + test_mp4_extra_metadata(); test_end_of_presentation(); test_release(); diff --git a/dlls/mfsrcsnk/tests/resource.rc b/dlls/mfsrcsnk/tests/resource.rc index 7b3a6532f0a..89d92ea3241 100644 --- a/dlls/mfsrcsnk/tests/resource.rc +++ b/dlls/mfsrcsnk/tests/resource.rc @@ -29,3 +29,18 @@ */ /* @makedep: test_thinning.avi */ test_thinning.avi RCDATA test_thinning.avi + +/* Generated with: + ffmpeg -filter_complex "smptebars=s=64x64[vout]" -map "[vout]" -t 0.25 -r 25 -vcodec h264 \ + -brand mp42 -aspect 3:4 -an test.mp4 + + Then, manually remove the pasp atom from the generated mp4 file. + */ +/* @makedep: test_metadata.mp4 */ +test_metadata.mp4 RCDATA test_metadata.mp4 + +/* Same as above, but instead of removing the pasp, it's modify to have an aspect ratio of 15:16 + * (it was 3:4 originally) + */ +/* @makedep: test_metadata2.mp4 */ +test_metadata2.mp4 RCDATA test_metadata2.mp4 diff --git a/dlls/mfsrcsnk/tests/test_metadata.mp4 b/dlls/mfsrcsnk/tests/test_metadata.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..9619569ed4b554a0c8a98bfef25a02c0fb1d73d1 GIT binary patch literal 1832 zcmZQzU{FXasVvAXFfn3aU}6B#nZ@}=iDk)#xdkSM3=AxmxhaVy3=9k$<(Vm|3=B*Q z*jWGnpL56c<=$sEJ+@ENxuI}V`Q7^pBQp~PU4`WQqErP#Fw;ZN$jn6FH^9|h*F?cF z%vm8hKP5F;L07>!zo0TFHLXO!$iTo@*T}%gR6$oEqokz3N?*Ucyj-s=GbJ@YCoxYi zzbIWFWUgLDNp6mUu0no6NoIatv6Vt{Vp3wVt)W6uYMQOFLP}~<PJVK>t)Z2Hm4QNH zUSdvVajLCBg|U@Eg`uIbLT;*UMrwsZacNR+s;#*~L2;$6A&87GO0hN6Gcd3+&@(Vl z$jz)sO^FAYXsD2z8ef!{m!4{CXr_>yQIwyX7@wPJYp76Cl$w*1S!`>lU{PU_l3ZeI zsE}NkYipp8lA4%Om7kYtYh<WnXsD2uSX>fcP@J7v08#-lps*l5KP{~|wZvA}NTDR7 zC^a#q*w#oPCqF+sF(WlGB_1Ybs8F1fnVgCcFi^-V0^5<CnVVPwaz|!fNor9}VsdJV zt${*PPH9nMWqfjeZb4#+t${*veqM1&QDSCZYD#=&UP)0RNKIN%Vs2`&t+7H<d_iSV zVs2)Nt&u`fd}2ys0mv6g@kyD9#UM*Ei&DY<Do@Q!&nQW<HB`tiNX?5+&o8hwP=E*) z*cvHhr&ea>mDn1Y8bF!xxtV#kMy3kI$*Fm%$)zQ>CI$*%+d)BElv<o&YoJh+91r&{ zNWLi9Hn}KGAvdX{C>7+b<f1fNBV#=Sg+h>LYz_3x3=|3rKn8>9#0pz8ONGLM;*!(? zTN8!Mg7~7ulFWQtLp>7%g~UQzLn}~hGBhwSFxsbfv@nEUUZQQ={?9;bW<x;Te~Dbz z<O$5}=k`5#Tpb~Hbi?<W`e{u|4~V{)|DvmbgW<_BN8f*UxN?L8UYZ`QG4_$owO*-s zo$>S<Z=t6<^it%@7r8GEv`IRrd(64?fAXp%r{}>=#h3kh#r_5!vrov8I}<#+z<$<& zNsDqPO%C1@sbp~`egnHd!_B1{zm#qr?c8-%aR%>g@fG4vpDfP0m;UVeCjKkT?zf!} z`Fin}zm^GpB`0?{!RWv4{q@4Tr>n{twXeH)$UglpPv%5PX-2Wa>Hhhf1E+dkog<~a zB7c5&a1opNP1Ox&>|Ec^zdhk>Qp1Z4%vRlXH3!o+hVK7zL;U^0O-oa>7M@F4mM;?| zelyG3A-efmmUqs}u>Z{4-rf=M{T=vb)q+~H^B1oz_{$oqeyHQh*6DwQvlC0MoN@f^ zR^JH9?vArma@^}VIKb?AP8EIsgB(F@#(9Y)PVx~B5O#8wlY9h7oX>Gqs^<#FjF~<h z&i^@gGB7Zm&&|&-V_;y&$t}xBVL$=QFBljYJ}@vcfDl545y1qr(D)!L!Q$8nMg|6^ z=#rwuYz78~n38O;oyaD@*dLI!g9X6^k|-J<Y%hoaVFt$Uxha{6pn@|u1#AbBMk59W z1|EjcBVZxLjFg-rFpGhK0aU2L*if2rU2bMx8Uq7^NLenrK@2J>5ILEYqEwI?kRFh; zcuI?M6d1ta#+X-Jl9a>1z%Z}4q!<>!AT@oU(i@}!q7KS}Q4S0a3?2*&U<?ui=>XBV zvBdxX3=9kwiDk*oj42FU{~t2Qr>8J*t-0x<_WuCG0Y<4tMy3S}49pA)3=C|Jk6bn# zU}Rv+c>Vaa(g6kr28rU5l47XgAiLN=^$Y_8gF`YxoDJeq7LYPV1_mxD4da8jpp?P{ zVlXl=fW<|MONx=r1(_{VTvD72QUoy%q=x}&HiJ%aNpTfa4n(mrFfcy{#}_Eh5LgHl OBgG}j`5;A5a|{5QSmr<g literal 0 HcmV?d00001 diff --git a/dlls/mfsrcsnk/tests/test_metadata2.mp4 b/dlls/mfsrcsnk/tests/test_metadata2.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..be4f6a7eb1d47721751982331bd32c22de128465 GIT binary patch literal 1848 zcmZQzU{FXasVvAXFfn3aU}6B#nZ@}=iDk)#xdkSM3=AxmxhaVy3=9k$<(Vm|3=B*Q z*jWGnpL56c<=$sEJ+@ENxuI}V`Q7^pBQp~PU4`WQqErP#Fw;ZN$jn6FH^9|h*F?cF z%vm8hKP5F;L07>!zo0TFHLXO!$iTo@*T}%gR6$oEqokz3N?*Ucyj-s=GbJ@YCoxYi zzbIWFWUgLDNp6mUu0no6NoIatv6Vt{Vp3wVt)W6uYMQOFLP}~<PJVK>t)Z2Hm4QNH zUSdvVajLCBg|U@Eg`uIbLT;*UMrwsZacNR+s;#*~L2;$6A&87GO0hN6Gcd3+&@(Vl z$jz)sO^FAYXsD2z8ef!{m!4{CXr_>yQIwyX7@wPJYp76Cl$w*1S!`>lU{PU_l3ZeI zsE}NkYipp8lA4%Om7kYtYh<WnXsD2uSX>fcP@J7v08#-lps*l5KP{~|wZvA}NTDR7 zC^a#q*w#oPCqF+sF(WlGB_1Ybs8F1fnVgCcFi^-V0^5<CnVVPwaz|!fNor9}VsdJV zt${*PPH9nMWqfjeZb4#+t${*veqM1&QDSCZYD#=&UP)0RNKIN%Vs2`&t+7H<d_iSV zVs2)Nt&u`fd}2ys0mv6g@kyD9#UM*Ei&DY<Do@Q!&nQW<HB`tiNX?5+&o8hwP=E*) z*cvHhr&ea>mDn1Y8bF!xxtV#kMy3kI$*Fm%$)zQ>CI$*%+d)BElv<o&YoJh+91r&{ zNWLi9Hn}KGAvdX{C>7+b<f1fNBV#=Sg+h>LYz_3x3=|3rKn8>9#0pz8ONGLM;*!(? zTN8!Mg7~7ulFWQtLp>7%g~UQzLn}~hGBhwSFxsbfv@nEUUZQQ={?9;bW<x;Te~Dbz z<O$5}=k`5#Tpb~Hbi?<W`e{u|4~V{)|DvmbgW<_BN8f*UxN?L8UYZ`QG4_$owO*-s zo$>S<Z=t6<^it%@7r8GEv`IRrd(64?fAXp%r{}>=#h3kh#r_5!vrov8I}<#+z<$<& zNsDqPO%C1@sbp~`egnHd!_B1{zm#qr?c8-%aR%>g@fG4vpDfP0m;UVeCjKkT?zf!} z`Fin}zm^GpB`0?{!RWv4{q@4Tr>n{twXeH)$UglpPv%5PX-2Wa>Hhhf1E+dkog<~a zB7c5&a1opNP1Ox&>|Ec^zdhk>Qp1Z4%vRlXH3!o+hVK7zL;U^0O-oa>7M@F4mM;?| zelyG3A-efmmUqs}u>Z{4-rf=M{T=vb)q+~H^B1oz_{$oqeyHQh*6DwQvlC0MoN@f^ zR^JH9?vArma@^}VIKb?AP8EIsgB(F@#(9Y)PVx~B5O#8wlY9h7oX>Gqs^<#FjF~<h z&i^@gGB7aR&&|&-V_;y&$t}xBVL$=QFBljYJ}@vcfDl545y1qr(D)!L!Q$8nMg|6^ z?2@9yYz78~n38O;oyaD@*dLI!g9X6^k|-J<Y%hoaVFo7l+?32jP{Em-0=5H5qY(oG z0}n&!5wMVAMoLZ*n8m=r04mgAY$(mRFE=wUje&tdq%0TRAO@8bh@4DHQ7T9cNDs(a zJf%fB3Jl<IW2`GKNy=ehU|3gNQVa`VkeYd*(i@}!q7KS}Q4S0a3?2*&U<?ui=>XBV zvBdxX3=9kwiDk*oj42FU{~t2Qr>8J*t-0x<_WuCG0Y<4tMy3S}49pA)3=C|Jk6bn# zU}Rv+c>Vaa(g6kr27!Xa;sOQ+27VBmfq_AyxTK^QY8l9GHc-98z`)>;j1XsoxSR!~ zjFEwX3rfTIATB87Fo7713=Cj#k>ZkKWOG4g%M_OsCxaA0%me9RfSS#qQ(RJ91(gF) cYzz#{&%yBribDhz0>w~qNpe0&5!4(50FG<tlmGw# literal 0 HcmV?d00001 -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10468
From: Yuxuan Shui <yshui@codeweavers.com> An H264 stream can contain aspect ratio information in its extradata, and that information is only made available after we have called avformat_find_stream_info. Doing so makes the aspect ratio information available from media sources, but only when winedmo is used. So the test case is updated to test winedmo specifically. --- dlls/winedmo/unix_demuxer.c | 38 +++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/dlls/winedmo/unix_demuxer.c b/dlls/winedmo/unix_demuxer.c index 4c6bc15579b..de7c8e76611 100644 --- a/dlls/winedmo/unix_demuxer.c +++ b/dlls/winedmo/unix_demuxer.c @@ -138,6 +138,7 @@ NTSTATUS demuxer_create( void *arg ) { struct demuxer_create_params *params = arg; const char *ext = params->url ? strrchr( params->url, '.' ) : ""; + BOOL needs_find_stream_info = FALSE; const AVInputFormat *format; struct demuxer *demuxer; int i, ret; @@ -155,16 +156,36 @@ NTSTATUS demuxer_create( void *arg ) } format = demuxer->ctx->iformat; + /* Determine if we need a call to avformat_find_stream_info. Some stream information is only + * available after calling it. */ if ((params->duration = get_context_duration( demuxer->ctx )) == AV_NOPTS_VALUE || strstr( format->name, "mp3" )) + needs_find_stream_info = TRUE; + + for (i = 0; i < demuxer->ctx->nb_streams && !needs_find_stream_info; i++) { - if ((ret = avformat_find_stream_info( demuxer->ctx, NULL )) < 0) - { - ERR( "Failed to find stream info, error %s.\n", debugstr_averr(ret) ); - goto failed; - } - params->duration = get_context_duration( demuxer->ctx ); + /* For H264 streams, sample aspect ratio is sometimes found in its sequence parameter set, + * which requires avformat_find_stream_info. */ + AVStream *stream = demuxer->ctx->streams[i]; + AVCodecParameters *par = stream->codecpar; + + if (par->codec_id != AV_CODEC_ID_H264) continue; + + /* If sample aspect ratio is available somewhere, skip find stream info. */ + if (stream->sample_aspect_ratio.den && stream->sample_aspect_ratio.num) continue; + if (par->sample_aspect_ratio.den && par->sample_aspect_ratio.num) continue; + + needs_find_stream_info = TRUE; } + + if (needs_find_stream_info && (ret = avformat_find_stream_info( demuxer->ctx, NULL )) < 0) + { + ERR( "Failed to find stream info, error %s.\n", debugstr_averr( ret ) ); + goto failed; + } + + if (params->duration == AV_NOPTS_VALUE) params->duration = get_context_duration( demuxer->ctx ); + if (!(demuxer->streams = calloc( demuxer->ctx->nb_streams, sizeof(*demuxer->streams) ))) goto failed; if (demuxer_create_streams( demuxer )) goto failed; @@ -367,11 +388,12 @@ NTSTATUS demuxer_stream_type( void *arg ) struct demuxer *demuxer = get_demuxer( params->demuxer ); AVStream *stream = demuxer->ctx->streams[params->stream]; AVCodecParameters *par = demuxer->streams[params->stream].filter->par_out; + AVRational sar = stream->sample_aspect_ratio; TRACE( "demuxer %p, stream %u, stream %p, index %u\n", demuxer, params->stream, stream, stream->index ); - return media_type_from_codec_params( par, &stream->sample_aspect_ratio, - &stream->avg_frame_rate, 0, ¶ms->media_type ); + if (!sar.den || !sar.num) sar = stream->codecpar->sample_aspect_ratio; + return media_type_from_codec_params( par, &sar, &stream->avg_frame_rate, 0, ¶ms->media_type ); } #endif /* HAVE_FFMPEG */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10468
This merge request was approved by Rémi Bernon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10468
participants (2)
-
Rémi Bernon (@rbernon) -
Yuxuan Shui