41
41
#include "libavutil/time.h"
42
42
#include "libavutil/imgutils.h"
43
43
#include "libavutil/film_grain_params.h"
44
+ #include <libavutil/reverse.h>
44
45
45
46
#include "avcodec.h"
46
47
#include "codec_internal.h"
49
50
#include "hwconfig.h"
50
51
#include "qsv.h"
51
52
#include "qsv_internal.h"
53
+ #include "h264_sei.h"
54
+ #include "hevc_ps.h"
55
+ #include "hevc_sei.h"
52
56
53
57
#if QSV_ONEVPL
54
58
#include <mfxdispatcher.h>
@@ -66,6 +70,8 @@ static const AVRational mfx_tb = { 1, 90000 };
66
70
AV_NOPTS_VALUE : pts_tb.num ? \
67
71
av_rescale_q(mfx_pts, mfx_tb, pts_tb) : mfx_pts)
68
72
73
+ #define PAYLOAD_BUFFER_SIZE 65535
74
+
69
75
typedef struct QSVAsyncFrame {
70
76
mfxSyncPoint * sync ;
71
77
QSVFrame * frame ;
@@ -107,6 +113,9 @@ typedef struct QSVContext {
107
113
108
114
mfxExtBuffer * * ext_buffers ;
109
115
int nb_ext_buffers ;
116
+
117
+ mfxU8 payload_buffer [PAYLOAD_BUFFER_SIZE ];
118
+ AVBufferRef * a53_buf_ref ;
110
119
} QSVContext ;
111
120
112
121
static const AVCodecHWConfigInternal * const qsv_hw_configs [] = {
@@ -628,6 +637,299 @@ static int qsv_export_film_grain(AVCodecContext *avctx, mfxExtAV1FilmGrainParam
628
637
}
629
638
#endif
630
639
640
+ static int find_start_offset (mfxU8 data [4 ])
641
+ {
642
+ if (data [0 ] == 0 && data [1 ] == 0 && data [2 ] == 1 )
643
+ return 3 ;
644
+
645
+ if (data [0 ] == 0 && data [1 ] == 0 && data [2 ] == 0 && data [3 ] == 1 )
646
+ return 4 ;
647
+
648
+ return 0 ;
649
+ }
650
+
651
+ static int parse_sei_h264 (AVCodecContext * avctx , QSVContext * q , AVFrame * out )
652
+ {
653
+ H264SEIContext sei = { 0 };
654
+ GetBitContext gb = { 0 };
655
+ mfxPayload payload = { 0 , .Data = & q -> payload_buffer [0 ], .BufSize = sizeof (q -> payload_buffer ) - AV_INPUT_BUFFER_PADDING_SIZE };
656
+ mfxU64 ts ;
657
+ int ret ;
658
+
659
+ while (1 ) {
660
+ int start ;
661
+ memset (payload .Data , 0 , payload .BufSize );
662
+
663
+ ret = MFXVideoDECODE_GetPayload (q -> session , & ts , & payload );
664
+ if (ret == MFX_ERR_NOT_ENOUGH_BUFFER ) {
665
+ av_log (avctx , AV_LOG_WARNING , "Warning: Insufficient buffer on GetPayload(). Size: %" PRIu64 " Needed: %d\n" , sizeof (q -> payload_buffer ), payload .BufSize );
666
+ return 0 ;
667
+ }
668
+ if (ret != MFX_ERR_NONE )
669
+ return ret ;
670
+
671
+ if (payload .NumBit == 0 || payload .NumBit >= payload .BufSize * 8 )
672
+ break ;
673
+
674
+ start = find_start_offset (payload .Data );
675
+
676
+ switch (payload .Type ) {
677
+ case SEI_TYPE_BUFFERING_PERIOD :
678
+ case SEI_TYPE_PIC_TIMING :
679
+ continue ;
680
+ }
681
+
682
+ if (init_get_bits (& gb , & payload .Data [start ], payload .NumBit - start * 8 ) < 0 )
683
+ av_log (avctx , AV_LOG_ERROR , "Error initializing bitstream reader SEI type: %d Numbits %d error: %d\n" , payload .Type , payload .NumBit , ret );
684
+ else {
685
+ ret = ff_h264_sei_decode (& sei , & gb , NULL , avctx );
686
+
687
+ if (ret < 0 )
688
+ av_log (avctx , AV_LOG_WARNING , "Failed to parse SEI type: %d Numbits %d error: %d\n" , payload .Type , payload .NumBit , ret );
689
+ else
690
+ av_log (avctx , AV_LOG_DEBUG , "mfxPayload Type: %d Numbits %d\n" , payload .Type , payload .NumBit );
691
+ }
692
+ }
693
+
694
+ if (out )
695
+ return ff_h264_set_sei_to_frame (avctx , & sei , out , NULL , 0 );
696
+
697
+ return 0 ;
698
+ }
699
+
700
+ static int parse_sei_hevc (AVCodecContext * avctx , QSVContext * q , QSVFrame * out )
701
+ {
702
+ HEVCSEI sei = { 0 };
703
+ HEVCParamSets ps = { 0 };
704
+ GetBitContext gb = { 0 };
705
+ mfxPayload payload = { 0 , .Data = & q -> payload_buffer [0 ], .BufSize = sizeof (q -> payload_buffer ) - AV_INPUT_BUFFER_PADDING_SIZE };
706
+ mfxFrameSurface1 * surface = & out -> surface ;
707
+ mfxU64 ts ;
708
+ int ret , has_logged = 0 ;
709
+
710
+ while (1 ) {
711
+ int start ;
712
+ memset (payload .Data , 0 , payload .BufSize );
713
+
714
+ ret = MFXVideoDECODE_GetPayload (q -> session , & ts , & payload );
715
+ if (ret == MFX_ERR_NOT_ENOUGH_BUFFER ) {
716
+ av_log (avctx , AV_LOG_WARNING , "Warning: Insufficient buffer on GetPayload(). Size: %" PRIu64 " Needed: %d\n" , sizeof (q -> payload_buffer ), payload .BufSize );
717
+ return 0 ;
718
+ }
719
+ if (ret != MFX_ERR_NONE )
720
+ return ret ;
721
+
722
+ if (payload .NumBit == 0 || payload .NumBit >= payload .BufSize * 8 )
723
+ break ;
724
+
725
+ if (!has_logged ) {
726
+ has_logged = 1 ;
727
+ av_log (avctx , AV_LOG_VERBOSE , "-----------------------------------------\n" );
728
+ av_log (avctx , AV_LOG_VERBOSE , "Start reading SEI - payload timestamp: %llu - surface timestamp: %llu\n" , ts , surface -> Data .TimeStamp );
729
+ }
730
+
731
+ if (ts != surface -> Data .TimeStamp ) {
732
+ av_log (avctx , AV_LOG_WARNING , "GetPayload timestamp (%llu) does not match surface timestamp: (%llu)\n" , ts , surface -> Data .TimeStamp );
733
+ }
734
+
735
+ start = find_start_offset (payload .Data );
736
+
737
+ av_log (avctx , AV_LOG_VERBOSE , "parsing SEI type: %3d Numbits %3d Start: %d\n" , payload .Type , payload .NumBit , start );
738
+
739
+ switch (payload .Type ) {
740
+ case SEI_TYPE_BUFFERING_PERIOD :
741
+ case SEI_TYPE_PIC_TIMING :
742
+ continue ;
743
+ case SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME :
744
+ // There seems to be a bug in MSDK
745
+ payload .NumBit -= 8 ;
746
+
747
+ break ;
748
+ case SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO :
749
+ // There seems to be a bug in MSDK
750
+ payload .NumBit = 48 ;
751
+
752
+ break ;
753
+ case SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35 :
754
+ // There seems to be a bug in MSDK
755
+ if (payload .NumBit == 552 )
756
+ payload .NumBit = 528 ;
757
+ break ;
758
+ }
759
+
760
+ if (init_get_bits (& gb , & payload .Data [start ], payload .NumBit - start * 8 ) < 0 )
761
+ av_log (avctx , AV_LOG_ERROR , "Error initializing bitstream reader SEI type: %d Numbits %d error: %d\n" , payload .Type , payload .NumBit , ret );
762
+ else {
763
+ ret = ff_hevc_decode_nal_sei (& gb , avctx , & sei , & ps , HEVC_NAL_SEI_PREFIX );
764
+
765
+ if (ret < 0 )
766
+ av_log (avctx , AV_LOG_WARNING , "Failed to parse SEI type: %d Numbits %d error: %d\n" , payload .Type , payload .NumBit , ret );
767
+ else
768
+ av_log (avctx , AV_LOG_DEBUG , "mfxPayload Type: %d Numbits %d\n" , payload .Type , payload .NumBit );
769
+ }
770
+ }
771
+
772
+ if (has_logged ) {
773
+ av_log (avctx , AV_LOG_VERBOSE , "End reading SEI\n" );
774
+ }
775
+
776
+ if (out && out -> frame )
777
+ return ff_hevc_set_sei_to_frame (avctx , & sei , out -> frame , avctx -> framerate , 0 , & ps .sps -> vui , ps .sps -> bit_depth , ps .sps -> bit_depth_chroma );
778
+
779
+ return 0 ;
780
+ }
781
+
782
+ #define A53_MAX_CC_COUNT 2000
783
+
784
+ static int mpeg_decode_a53_cc (AVCodecContext * avctx , QSVContext * s ,
785
+ const uint8_t * p , int buf_size )
786
+ {
787
+ if (buf_size >= 6 &&
788
+ p [0 ] == 'G' && p [1 ] == 'A' && p [2 ] == '9' && p [3 ] == '4' &&
789
+ p [4 ] == 3 && (p [5 ] & 0x40 )) {
790
+ /* extract A53 Part 4 CC data */
791
+ unsigned cc_count = p [5 ] & 0x1f ;
792
+ if (cc_count > 0 && buf_size >= 7 + cc_count * 3 ) {
793
+ const uint64_t old_size = s -> a53_buf_ref ? s -> a53_buf_ref -> size : 0 ;
794
+ const uint64_t new_size = (old_size + cc_count
795
+ * UINT64_C (3 ));
796
+ int ret ;
797
+
798
+ if (new_size > 3 * A53_MAX_CC_COUNT )
799
+ return AVERROR (EINVAL );
800
+
801
+ ret = av_buffer_realloc (& s -> a53_buf_ref , new_size );
802
+ if (ret >= 0 )
803
+ memcpy (s -> a53_buf_ref -> data + old_size , p + 7 , cc_count * UINT64_C (3 ));
804
+
805
+ avctx -> properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS ;
806
+ }
807
+ return 1 ;
808
+ } else if (buf_size >= 2 && p [0 ] == 0x03 && (p [1 ]& 0x7f ) == 0x01 ) {
809
+ /* extract SCTE-20 CC data */
810
+ GetBitContext gb ;
811
+ unsigned cc_count = 0 ;
812
+ int ret ;
813
+
814
+ init_get_bits8 (& gb , p + 2 , buf_size - 2 );
815
+ cc_count = get_bits (& gb , 5 );
816
+ if (cc_count > 0 ) {
817
+ uint64_t old_size = s -> a53_buf_ref ? s -> a53_buf_ref -> size : 0 ;
818
+ uint64_t new_size = (old_size + cc_count * UINT64_C (3 ));
819
+ if (new_size > 3 * A53_MAX_CC_COUNT )
820
+ return AVERROR (EINVAL );
821
+
822
+ ret = av_buffer_realloc (& s -> a53_buf_ref , new_size );
823
+ if (ret >= 0 ) {
824
+ uint8_t field , cc1 , cc2 ;
825
+ uint8_t * cap = s -> a53_buf_ref -> data ;
826
+
827
+ memset (s -> a53_buf_ref -> data + old_size , 0 , cc_count * 3 );
828
+ for (unsigned i = 0 ; i < cc_count && get_bits_left (& gb ) >= 26 ; i ++ ) {
829
+ skip_bits (& gb , 2 ); // priority
830
+ field = get_bits (& gb , 2 );
831
+ skip_bits (& gb , 5 ); // line_offset
832
+ cc1 = get_bits (& gb , 8 );
833
+ cc2 = get_bits (& gb , 8 );
834
+ skip_bits (& gb , 1 ); // marker
835
+
836
+ if (!field ) { // forbidden
837
+ cap [0 ] = cap [1 ] = cap [2 ] = 0x00 ;
838
+ } else {
839
+ field = (field == 2 ? 1 : 0 );
840
+ ////if (!s1->mpeg_enc_ctx.top_field_first) field = !field;
841
+ cap [0 ] = 0x04 | field ;
842
+ cap [1 ] = ff_reverse [cc1 ];
843
+ cap [2 ] = ff_reverse [cc2 ];
844
+ }
845
+ cap += 3 ;
846
+ }
847
+ }
848
+ avctx -> properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS ;
849
+ }
850
+ return 1 ;
851
+ } else if (buf_size >= 11 && p [0 ] == 'C' && p [1 ] == 'C' && p [2 ] == 0x01 && p [3 ] == 0xf8 ) {
852
+ int cc_count = 0 ;
853
+ int i , ret ;
854
+ // There is a caption count field in the data, but it is often
855
+ // incorrect. So count the number of captions present.
856
+ for (i = 5 ; i + 6 <= buf_size && ((p [i ] & 0xfe ) == 0xfe ); i += 6 )
857
+ cc_count ++ ;
858
+ // Transform the DVD format into A53 Part 4 format
859
+ if (cc_count > 0 ) {
860
+ int old_size = s -> a53_buf_ref ? s -> a53_buf_ref -> size : 0 ;
861
+ uint64_t new_size = (old_size + cc_count
862
+ * UINT64_C (6 ));
863
+ if (new_size > 3 * A53_MAX_CC_COUNT )
864
+ return AVERROR (EINVAL );
865
+
866
+ ret = av_buffer_realloc (& s -> a53_buf_ref , new_size );
867
+ if (ret >= 0 ) {
868
+ uint8_t field1 = !!(p [4 ] & 0x80 );
869
+ uint8_t * cap = s -> a53_buf_ref -> data ;
870
+ p += 5 ;
871
+ for (i = 0 ; i < cc_count ; i ++ ) {
872
+ cap [0 ] = (p [0 ] == 0xff && field1 ) ? 0xfc : 0xfd ;
873
+ cap [1 ] = p [1 ];
874
+ cap [2 ] = p [2 ];
875
+ cap [3 ] = (p [3 ] == 0xff && !field1 ) ? 0xfc : 0xfd ;
876
+ cap [4 ] = p [4 ];
877
+ cap [5 ] = p [5 ];
878
+ cap += 6 ;
879
+ p += 6 ;
880
+ }
881
+ }
882
+ avctx -> properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS ;
883
+ }
884
+ return 1 ;
885
+ }
886
+ return 0 ;
887
+ }
888
+
889
+ static int parse_sei_mpeg12 (AVCodecContext * avctx , QSVContext * q , AVFrame * out )
890
+ {
891
+ mfxPayload payload = { 0 , .Data = & q -> payload_buffer [0 ], .BufSize = sizeof (q -> payload_buffer ) - AV_INPUT_BUFFER_PADDING_SIZE };
892
+ mfxU64 ts ;
893
+ int ret ;
894
+
895
+ while (1 ) {
896
+ int start ;
897
+
898
+ memset (payload .Data , 0 , payload .BufSize );
899
+ ret = MFXVideoDECODE_GetPayload (q -> session , & ts , & payload );
900
+ if (ret == MFX_ERR_NOT_ENOUGH_BUFFER ) {
901
+ av_log (avctx , AV_LOG_WARNING , "Warning: Insufficient buffer on GetPayload(). Size: %" PRIu64 " Needed: %d\n" , sizeof (q -> payload_buffer ), payload .BufSize );
902
+ return 0 ;
903
+ }
904
+ if (ret != MFX_ERR_NONE )
905
+ return ret ;
906
+
907
+ if (payload .NumBit == 0 || payload .NumBit >= payload .BufSize * 8 )
908
+ break ;
909
+
910
+ start = find_start_offset (payload .Data );
911
+
912
+ start ++ ;
913
+
914
+ mpeg_decode_a53_cc (avctx , q , & payload .Data [start ], (int )((payload .NumBit + 7 ) / 8 ) - start );
915
+
916
+ av_log (avctx , AV_LOG_DEBUG , "mfxPayload Type: %d Numbits %d start %d -> %.s\n" , payload .Type , payload .NumBit , start , (char * )(& payload .Data [start ]));
917
+ }
918
+
919
+ if (!out )
920
+ return 0 ;
921
+
922
+ if (q -> a53_buf_ref ) {
923
+
924
+ AVFrameSideData * sd = av_frame_new_side_data_from_buf (out , AV_FRAME_DATA_A53_CC , q -> a53_buf_ref );
925
+ if (!sd )
926
+ av_buffer_unref (& q -> a53_buf_ref );
927
+ q -> a53_buf_ref = NULL ;
928
+ }
929
+
930
+ return 0 ;
931
+ }
932
+
631
933
static int qsv_decode (AVCodecContext * avctx , QSVContext * q ,
632
934
AVFrame * frame , int * got_frame ,
633
935
const AVPacket * avpkt )
@@ -664,6 +966,8 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q,
664
966
insurf , & outsurf , sync );
665
967
if (ret == MFX_WRN_DEVICE_BUSY )
666
968
av_usleep (500 );
969
+ else if (avctx -> codec_id == AV_CODEC_ID_MPEG2VIDEO )
970
+ parse_sei_mpeg12 (avctx , q , NULL );
667
971
668
972
} while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE );
669
973
@@ -705,6 +1009,23 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q,
705
1009
return AVERROR_BUG ;
706
1010
}
707
1011
1012
+ switch (avctx -> codec_id ) {
1013
+ case AV_CODEC_ID_MPEG2VIDEO :
1014
+ ret = parse_sei_mpeg12 (avctx , q , out_frame -> frame );
1015
+ break ;
1016
+ case AV_CODEC_ID_H264 :
1017
+ ret = parse_sei_h264 (avctx , q , out_frame -> frame );
1018
+ break ;
1019
+ case AV_CODEC_ID_HEVC :
1020
+ ret = parse_sei_hevc (avctx , q , out_frame );
1021
+ break ;
1022
+ default :
1023
+ ret = 0 ;
1024
+ }
1025
+
1026
+ if (ret < 0 )
1027
+ av_log (avctx , AV_LOG_ERROR , "Error parsing SEI data: %d\n" , ret );
1028
+
708
1029
out_frame -> queued += 1 ;
709
1030
710
1031
aframe = (QSVAsyncFrame ){ sync , out_frame };
0 commit comments