summarylogtreecommitdiffstats
path: root/0002-rkmpp-4.patch
blob: 9446714d30cc5e521ddda8eabd7afe909be4cd74 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
From 9590c16111eb27ba8cb1b5c46ea57dc9052e82ed Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Wed, 4 Sep 2019 17:24:37 +0800
Subject: [PATCH 01/18] avcodec/rkmppdec: Clear eos flag after reset

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 libavcodec/rkmppdec.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index a60962dc86..3654437268 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -544,6 +544,7 @@ static void rkmpp_flush(AVCodecContext *avctx)
     ret = decoder->mpi->reset(decoder->ctx);
     if (ret == MPP_OK) {
         decoder->first_packet = 1;
+        decoder->eos_reached = 0;
     } else
         av_log(avctx, AV_LOG_ERROR, "Failed to reset MPI (code = %d)\n", ret);
 }
-- 
2.40.0


From 43fc7807c58999a57d4c407dcda0d3d2fac7405b Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Wed, 4 Sep 2019 17:27:46 +0800
Subject: [PATCH 02/18] avcodec/rkmppdec: Compatible with old reordered_opaque
 and pkt_pts

Some users might still using these deprecated APIs.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 libavcodec/rkmppdec.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index 3654437268..6256abe63c 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -93,6 +93,9 @@ static int rkmpp_write_data(AVCodecContext *avctx, uint8_t *buffer, int size, in
     int ret;
     MppPacket packet;
 
+    if (!pts || pts == AV_NOPTS_VALUE)
+        pts = avctx->reordered_opaque;
+
     // create the MPP packet
     ret = mpp_packet_init(&packet, buffer, size);
     if (ret != MPP_OK) {
@@ -398,6 +401,12 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame)
         frame->width            = mpp_frame_get_width(mppframe);
         frame->height           = mpp_frame_get_height(mppframe);
         frame->pts              = mpp_frame_get_pts(mppframe);
+#if FF_API_PKT_PTS
+        FF_DISABLE_DEPRECATION_WARNINGS
+        frame->pkt_pts          = frame->pts;
+        FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+        frame->reordered_opaque = frame->pts;
         frame->color_range      = mpp_frame_get_color_range(mppframe);
         frame->color_primaries  = mpp_frame_get_color_primaries(mppframe);
         frame->color_trc        = mpp_frame_get_color_trc(mppframe);
-- 
2.40.0


From 6b5e686cea5638fe6c2c92eeaaabe16d9a72121b Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Wed, 19 May 2021 09:55:03 +0800
Subject: [PATCH 03/18] rkmppdec: Remove frame buffer limit

It would hang when reaching the limit.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 libavcodec/rkmppdec.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index 6256abe63c..96696e84dc 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -39,7 +39,6 @@
 #include "libavutil/log.h"
 
 #define RECEIVE_FRAME_TIMEOUT   100
-#define FRAMEGROUP_MAX_FRAMES   16
 #define INPUT_MAX_PACKETS       4
 
 typedef struct {
@@ -241,13 +240,6 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
         goto fail;
     }
 
-    ret = mpp_buffer_group_limit_config(decoder->frame_group, 0, FRAMEGROUP_MAX_FRAMES);
-    if (ret) {
-        av_log(avctx, AV_LOG_ERROR, "Failed to set buffer group limit (code = %d)\n", ret);
-        ret = AVERROR_UNKNOWN;
-        goto fail;
-    }
-
     decoder->first_packet = 1;
 
     av_log(avctx, AV_LOG_DEBUG, "RKMPP decoder initialized successfully.\n");
-- 
2.40.0


From 668ec8c36d1112c5c4939ddc3d3b7cff487cedc1 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Thu, 20 May 2021 10:19:15 +0800
Subject: [PATCH 04/18] avcodec/rkmppdec: Rework decoding flow

Stop using the deprecated MPP_DEC_GET_STREAM_COUNT API.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 libavcodec/rkmppdec.c | 526 ++++++++++++++++++++++--------------------
 1 file changed, 270 insertions(+), 256 deletions(-)

diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index 96696e84dc..7c28378120 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -38,17 +38,15 @@
 #include "libavutil/imgutils.h"
 #include "libavutil/log.h"
 
-#define RECEIVE_FRAME_TIMEOUT   100
-#define INPUT_MAX_PACKETS       4
-
 typedef struct {
     MppCtx ctx;
     MppApi *mpi;
     MppBufferGroup frame_group;
 
-    char first_packet;
-    char eos_reached;
+    int8_t eos;
+    int8_t draining;
 
+    AVPacket packet;
     AVBufferRef *frames_ref;
     AVBufferRef *device_ref;
 } RKMPPDecoder;
@@ -85,47 +83,13 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
     }
 }
 
-static int rkmpp_write_data(AVCodecContext *avctx, uint8_t *buffer, int size, int64_t pts)
+static int rkmpp_close_decoder(AVCodecContext *avctx)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
     RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
-    int ret;
-    MppPacket packet;
-
-    if (!pts || pts == AV_NOPTS_VALUE)
-        pts = avctx->reordered_opaque;
-
-    // create the MPP packet
-    ret = mpp_packet_init(&packet, buffer, size);
-    if (ret != MPP_OK) {
-        av_log(avctx, AV_LOG_ERROR, "Failed to init MPP packet (code = %d)\n", ret);
-        return AVERROR_UNKNOWN;
-    }
-
-    mpp_packet_set_pts(packet, pts);
-
-    if (!buffer)
-        mpp_packet_set_eos(packet);
 
-    ret = decoder->mpi->decode_put_packet(decoder->ctx, packet);
-    if (ret != MPP_OK) {
-        if (ret == MPP_ERR_BUFFER_FULL) {
-            av_log(avctx, AV_LOG_DEBUG, "Buffer full writing %d bytes to decoder\n", size);
-            ret = AVERROR(EAGAIN);
-        } else
-            ret = AVERROR_UNKNOWN;
-    }
-    else
-        av_log(avctx, AV_LOG_DEBUG, "Wrote %d bytes to decoder\n", size);
+    av_packet_unref(&decoder->packet);
 
-    mpp_packet_deinit(&packet);
-
-    return ret;
-}
-
-static int rkmpp_close_decoder(AVCodecContext *avctx)
-{
-    RKMPPDecodeContext *rk_context = avctx->priv_data;
     av_buffer_unref(&rk_context->decoder_ref);
     return 0;
 }
@@ -151,14 +115,32 @@ static void rkmpp_release_decoder(void *opaque, uint8_t *data)
     av_free(decoder);
 }
 
+static int rkmpp_prepare_decoder(AVCodecContext *avctx)
+{
+    RKMPPDecodeContext *rk_context = avctx->priv_data;
+    RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+    MppPacket packet;
+    int ret;
+
+    // send extra data
+    if (avctx->extradata_size) {
+        ret = mpp_packet_init(&packet, avctx->extradata, avctx->extradata_size);
+        if (ret < 0)
+            return AVERROR_UNKNOWN;
+        ret = decoder->mpi->decode_put_packet(decoder->ctx, packet);
+        mpp_packet_deinit(&packet);
+        if (ret < 0)
+            return AVERROR_UNKNOWN;
+    }
+    return 0;
+}
+
 static int rkmpp_init_decoder(AVCodecContext *avctx)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
     RKMPPDecoder *decoder = NULL;
     MppCodingType codectype = MPP_VIDEO_CodingUnused;
     int ret;
-    RK_S64 paramS64;
-    RK_S32 paramS32;
 
     avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME;
 
@@ -201,6 +183,9 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
         goto fail;
     }
 
+    ret = 1;
+    decoder->mpi->control(decoder->ctx, MPP_DEC_SET_PARSER_FAST_MODE, &ret);
+
     // initialize mpp
     ret = mpp_init(decoder->ctx, MPP_CTX_DEC, codectype);
     if (ret != MPP_OK) {
@@ -209,26 +194,9 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
         goto fail;
     }
 
-    // make decode calls blocking with a timeout
-    paramS32 = MPP_POLL_BLOCK;
-    ret = decoder->mpi->control(decoder->ctx, MPP_SET_OUTPUT_BLOCK, &paramS32);
-    if (ret != MPP_OK) {
-        av_log(avctx, AV_LOG_ERROR, "Failed to set blocking mode on MPI (code = %d).\n", ret);
-        ret = AVERROR_UNKNOWN;
-        goto fail;
-    }
-
-    paramS64 = RECEIVE_FRAME_TIMEOUT;
-    ret = decoder->mpi->control(decoder->ctx, MPP_SET_OUTPUT_BLOCK_TIMEOUT, &paramS64);
-    if (ret != MPP_OK) {
-        av_log(avctx, AV_LOG_ERROR, "Failed to set block timeout on MPI (code = %d).\n", ret);
-        ret = AVERROR_UNKNOWN;
-        goto fail;
-    }
-
     ret = mpp_buffer_group_get_internal(&decoder->frame_group, MPP_BUFFER_TYPE_ION);
     if (ret) {
-       av_log(avctx, AV_LOG_ERROR, "Failed to retrieve buffer group (code = %d)\n", ret);
+       av_log(avctx, AV_LOG_ERROR, "Failed to get buffer group (code = %d)\n", ret);
        ret = AVERROR_UNKNOWN;
        goto fail;
     }
@@ -240,7 +208,13 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
         goto fail;
     }
 
-    decoder->first_packet = 1;
+    decoder->mpi->control(decoder->ctx, MPP_DEC_SET_DISABLE_ERROR, NULL);
+
+    ret = rkmpp_prepare_decoder(avctx);
+    if (ret < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to prepare decoder (code = %d)\n", ret);
+        goto fail;
+    }
 
     av_log(avctx, AV_LOG_DEBUG, "RKMPP decoder initialized successfully.\n");
 
@@ -261,44 +235,6 @@ fail:
     return ret;
 }
 
-static int rkmpp_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
-{
-    RKMPPDecodeContext *rk_context = avctx->priv_data;
-    RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
-    int ret;
-
-    // handle EOF
-    if (!avpkt->size) {
-        av_log(avctx, AV_LOG_DEBUG, "End of stream.\n");
-        decoder->eos_reached = 1;
-        ret = rkmpp_write_data(avctx, NULL, 0, 0);
-        if (ret)
-            av_log(avctx, AV_LOG_ERROR, "Failed to send EOS to decoder (code = %d)\n", ret);
-        return ret;
-    }
-
-    // on first packet, send extradata
-    if (decoder->first_packet) {
-        if (avctx->extradata_size) {
-            ret = rkmpp_write_data(avctx, avctx->extradata,
-                                            avctx->extradata_size,
-                                            avpkt->pts);
-            if (ret) {
-                av_log(avctx, AV_LOG_ERROR, "Failed to write extradata to decoder (code = %d)\n", ret);
-                return ret;
-            }
-        }
-        decoder->first_packet = 0;
-    }
-
-    // now send packet
-    ret = rkmpp_write_data(avctx, avpkt->data, avpkt->size, avpkt->pts);
-    if (ret && ret!=AVERROR(EAGAIN))
-        av_log(avctx, AV_LOG_ERROR, "Failed to write data to decoder (code = %d)\n", ret);
-
-    return ret;
-}
-
 static void rkmpp_release_frame(void *opaque, uint8_t *data)
 {
     AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)data;
@@ -312,7 +248,7 @@ static void rkmpp_release_frame(void *opaque, uint8_t *data)
     av_free(desc);
 }
 
-static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame)
+static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
     RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
@@ -327,156 +263,164 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame)
     MppFrameFormat mppformat;
     uint32_t drmformat;
 
+    // should not provide any frame after EOS
+    if (decoder->eos)
+        return AVERROR_EOF;
+
+    decoder->mpi->control(decoder->ctx, MPP_SET_OUTPUT_TIMEOUT, (MppParam)&timeout);
+
     ret = decoder->mpi->decode_get_frame(decoder->ctx, &mppframe);
     if (ret != MPP_OK && ret != MPP_ERR_TIMEOUT) {
-        av_log(avctx, AV_LOG_ERROR, "Failed to get a frame from MPP (code = %d)\n", ret);
-        goto fail;
+        av_log(avctx, AV_LOG_ERROR, "Failed to get frame (code = %d)\n", ret);
+        return AVERROR_UNKNOWN;
     }
 
-    if (mppframe) {
-        // Check whether we have a special frame or not
-        if (mpp_frame_get_info_change(mppframe)) {
-            AVHWFramesContext *hwframes;
+    if (!mppframe) {
+        av_log(avctx, AV_LOG_DEBUG, "Timeout getting decoded frame.\n");
+        return AVERROR(EAGAIN);
+    }
 
-            av_log(avctx, AV_LOG_INFO, "Decoder noticed an info change (%dx%d), format=%d\n",
-                                        (int)mpp_frame_get_width(mppframe), (int)mpp_frame_get_height(mppframe),
-                                        (int)mpp_frame_get_fmt(mppframe));
+    if (mpp_frame_get_eos(mppframe)) {
+        av_log(avctx, AV_LOG_DEBUG, "Received a EOS frame.\n");
+        decoder->eos = 1;
+        ret = AVERROR_EOF;
+        goto fail;
+    }
 
-            avctx->width = mpp_frame_get_width(mppframe);
-            avctx->height = mpp_frame_get_height(mppframe);
+    if (mpp_frame_get_discard(mppframe)) {
+        av_log(avctx, AV_LOG_DEBUG, "Received a discard frame.\n");
+        ret = AVERROR(EAGAIN);
+        goto fail;
+    }
 
-            decoder->mpi->control(decoder->ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
+    if (mpp_frame_get_errinfo(mppframe)) {
+        av_log(avctx, AV_LOG_ERROR, "Received a errinfo frame.\n");
+        ret = AVERROR_UNKNOWN;
+        goto fail;
+    }
 
-            av_buffer_unref(&decoder->frames_ref);
+    if (mpp_frame_get_info_change(mppframe)) {
+        AVHWFramesContext *hwframes;
 
-            decoder->frames_ref = av_hwframe_ctx_alloc(decoder->device_ref);
-            if (!decoder->frames_ref) {
-                ret = AVERROR(ENOMEM);
-                goto fail;
-            }
+        av_log(avctx, AV_LOG_INFO, "Decoder noticed an info change (%dx%d), format=%d\n",
+               (int)mpp_frame_get_width(mppframe), (int)mpp_frame_get_height(mppframe),
+               (int)mpp_frame_get_fmt(mppframe));
 
-            mppformat = mpp_frame_get_fmt(mppframe);
-            drmformat = rkmpp_get_frameformat(mppformat);
+        avctx->width = mpp_frame_get_width(mppframe);
+        avctx->height = mpp_frame_get_height(mppframe);
 
-            hwframes = (AVHWFramesContext*)decoder->frames_ref->data;
-            hwframes->format    = AV_PIX_FMT_DRM_PRIME;
-            hwframes->sw_format = drmformat == DRM_FORMAT_NV12 ? AV_PIX_FMT_NV12 : AV_PIX_FMT_NONE;
-            hwframes->width     = avctx->width;
-            hwframes->height    = avctx->height;
-            ret = av_hwframe_ctx_init(decoder->frames_ref);
-            if (ret < 0)
-                goto fail;
+        decoder->mpi->control(decoder->ctx, MPP_DEC_SET_FRAME_INFO, (MppParam) mppframe);
+        decoder->mpi->control(decoder->ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
 
-            // here decoder is fully initialized, we need to feed it again with data
-            ret = AVERROR(EAGAIN);
-            goto fail;
-        } else if (mpp_frame_get_eos(mppframe)) {
-            av_log(avctx, AV_LOG_DEBUG, "Received a EOS frame.\n");
-            decoder->eos_reached = 1;
-            ret = AVERROR_EOF;
-            goto fail;
-        } else if (mpp_frame_get_discard(mppframe)) {
-            av_log(avctx, AV_LOG_DEBUG, "Received a discard frame.\n");
-            ret = AVERROR(EAGAIN);
-            goto fail;
-        } else if (mpp_frame_get_errinfo(mppframe)) {
-            av_log(avctx, AV_LOG_ERROR, "Received a errinfo frame.\n");
-            ret = AVERROR_UNKNOWN;
+        av_buffer_unref(&decoder->frames_ref);
+
+        decoder->frames_ref = av_hwframe_ctx_alloc(decoder->device_ref);
+        if (!decoder->frames_ref) {
+            ret = AVERROR(ENOMEM);
             goto fail;
         }
 
-        // here we should have a valid frame
-        av_log(avctx, AV_LOG_DEBUG, "Received a frame.\n");
+        mppformat = mpp_frame_get_fmt(mppframe);
+        drmformat = rkmpp_get_frameformat(mppformat);
+
+        hwframes = (AVHWFramesContext*)decoder->frames_ref->data;
+        hwframes->format    = AV_PIX_FMT_DRM_PRIME;
+        hwframes->sw_format = drmformat == DRM_FORMAT_NV12 ? AV_PIX_FMT_NV12 : AV_PIX_FMT_NONE;
+        hwframes->width     = avctx->width;
+        hwframes->height    = avctx->height;
+        ret = av_hwframe_ctx_init(decoder->frames_ref);
+        if (!ret)
+            ret = AVERROR(EAGAIN);
+
+        goto fail;
+    }
 
-        // setup general frame fields
-        frame->format           = AV_PIX_FMT_DRM_PRIME;
-        frame->width            = mpp_frame_get_width(mppframe);
-        frame->height           = mpp_frame_get_height(mppframe);
-        frame->pts              = mpp_frame_get_pts(mppframe);
+    // here we should have a valid frame
+    av_log(avctx, AV_LOG_DEBUG, "Received a frame.\n");
+
+    // now setup the frame buffer info
+    buffer = mpp_frame_get_buffer(mppframe);
+    if (!buffer) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to get the frame buffer, frame is dropped (code = %d)\n", ret);
+        ret = AVERROR(EAGAIN);
+        goto fail;
+    }
+
+    // setup general frame fields
+    frame->format           = avctx->pix_fmt;
+    frame->width            = mpp_frame_get_width(mppframe);
+    frame->height           = mpp_frame_get_height(mppframe);
+    frame->pts              = mpp_frame_get_pts(mppframe);
 #if FF_API_PKT_PTS
-        FF_DISABLE_DEPRECATION_WARNINGS
-        frame->pkt_pts          = frame->pts;
-        FF_ENABLE_DEPRECATION_WARNINGS
+    FF_DISABLE_DEPRECATION_WARNINGS;
+    frame->pkt_pts          = frame->pts;
+    FF_ENABLE_DEPRECATION_WARNINGS;
 #endif
-        frame->reordered_opaque = frame->pts;
-        frame->color_range      = mpp_frame_get_color_range(mppframe);
-        frame->color_primaries  = mpp_frame_get_color_primaries(mppframe);
-        frame->color_trc        = mpp_frame_get_color_trc(mppframe);
-        frame->colorspace       = mpp_frame_get_colorspace(mppframe);
+    frame->reordered_opaque = frame->pts;
+    frame->color_range      = mpp_frame_get_color_range(mppframe);
+    frame->color_primaries  = mpp_frame_get_color_primaries(mppframe);
+    frame->color_trc        = mpp_frame_get_color_trc(mppframe);
+    frame->colorspace       = mpp_frame_get_colorspace(mppframe);
 
-        mode = mpp_frame_get_mode(mppframe);
-        frame->interlaced_frame = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED);
-        frame->top_field_first  = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST);
+    mode = mpp_frame_get_mode(mppframe);
+    frame->interlaced_frame = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED);
+    frame->top_field_first  = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST);
 
-        mppformat = mpp_frame_get_fmt(mppframe);
-        drmformat = rkmpp_get_frameformat(mppformat);
+    mppformat = mpp_frame_get_fmt(mppframe);
+    drmformat = rkmpp_get_frameformat(mppformat);
 
-        // now setup the frame buffer info
-        buffer = mpp_frame_get_buffer(mppframe);
-        if (buffer) {
-            desc = av_mallocz(sizeof(AVDRMFrameDescriptor));
-            if (!desc) {
-                ret = AVERROR(ENOMEM);
-                goto fail;
-            }
+    desc = av_mallocz(sizeof(AVDRMFrameDescriptor));
+    if (!desc) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
 
-            desc->nb_objects = 1;
-            desc->objects[0].fd = mpp_buffer_get_fd(buffer);
-            desc->objects[0].size = mpp_buffer_get_size(buffer);
-
-            desc->nb_layers = 1;
-            layer = &desc->layers[0];
-            layer->format = drmformat;
-            layer->nb_planes = 2;
-
-            layer->planes[0].object_index = 0;
-            layer->planes[0].offset = 0;
-            layer->planes[0].pitch = mpp_frame_get_hor_stride(mppframe);
-
-            layer->planes[1].object_index = 0;
-            layer->planes[1].offset = layer->planes[0].pitch * mpp_frame_get_ver_stride(mppframe);
-            layer->planes[1].pitch = layer->planes[0].pitch;
-
-            // we also allocate a struct in buf[0] that will allow to hold additionnal information
-            // for releasing properly MPP frames and decoder
-            framecontextref = av_buffer_allocz(sizeof(*framecontext));
-            if (!framecontextref) {
-                ret = AVERROR(ENOMEM);
-                goto fail;
-            }
+    desc->nb_objects = 1;
+    desc->objects[0].fd = mpp_buffer_get_fd(buffer);
+    desc->objects[0].size = mpp_buffer_get_size(buffer);
 
-            // MPP decoder needs to be closed only when all frames have been released.
-            framecontext = (RKMPPFrameContext *)framecontextref->data;
-            framecontext->decoder_ref = av_buffer_ref(rk_context->decoder_ref);
-            framecontext->frame = mppframe;
+    desc->nb_layers = 1;
+    layer = &desc->layers[0];
+    layer->format = drmformat;
+    layer->nb_planes = 2;
 
-            frame->data[0]  = (uint8_t *)desc;
-            frame->buf[0]   = av_buffer_create((uint8_t *)desc, sizeof(*desc), rkmpp_release_frame,
-                                               framecontextref, AV_BUFFER_FLAG_READONLY);
+    layer->planes[0].object_index = 0;
+    layer->planes[0].offset = 0;
+    layer->planes[0].pitch = mpp_frame_get_hor_stride(mppframe);
 
-            if (!frame->buf[0]) {
-                ret = AVERROR(ENOMEM);
-                goto fail;
-            }
+    layer->planes[1].object_index = 0;
+    layer->planes[1].offset = layer->planes[0].pitch * mpp_frame_get_ver_stride(mppframe);
+    layer->planes[1].pitch = layer->planes[0].pitch;
 
-            frame->hw_frames_ctx = av_buffer_ref(decoder->frames_ref);
-            if (!frame->hw_frames_ctx) {
-                ret = AVERROR(ENOMEM);
-                goto fail;
-            }
+    // we also allocate a struct in buf[0] that will allow to hold additionnal information
+    // for releasing properly MPP frames and decoder
+    framecontextref = av_buffer_allocz(sizeof(*framecontext));
+    if (!framecontextref) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
 
-            return 0;
-        } else {
-            av_log(avctx, AV_LOG_ERROR, "Failed to retrieve the frame buffer, frame is dropped (code = %d)\n", ret);
-            mpp_frame_deinit(&mppframe);
-        }
-    } else if (decoder->eos_reached) {
-        return AVERROR_EOF;
-    } else if (ret == MPP_ERR_TIMEOUT) {
-        av_log(avctx, AV_LOG_DEBUG, "Timeout when trying to get a frame from MPP\n");
+    // MPP decoder needs to be closed only when all frames have been released.
+    framecontext = (RKMPPFrameContext *)framecontextref->data;
+    framecontext->decoder_ref = av_buffer_ref(rk_context->decoder_ref);
+    framecontext->frame = mppframe;
+
+    frame->data[0]  = (uint8_t *)desc;
+    frame->buf[0]   = av_buffer_create((uint8_t *)desc, sizeof(*desc), rkmpp_release_frame,
+                                       framecontextref, AV_BUFFER_FLAG_READONLY);
+
+    if (!frame->buf[0]) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
     }
 
-    return AVERROR(EAGAIN);
+    frame->hw_frames_ctx = av_buffer_ref(decoder->frames_ref);
+    if (!frame->hw_frames_ctx) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    return 0;
 
 fail:
     if (mppframe)
@@ -494,60 +438,130 @@ fail:
     return ret;
 }
 
+static int rkmpp_send_packet(AVCodecContext *avctx, AVPacket *packet)
+{
+    RKMPPDecodeContext *rk_context = avctx->priv_data;
+    RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+    MppPacket mpkt;
+    int64_t pts = packet->pts;
+    int ret;
+
+    // avoid sending new data after EOS
+    if (decoder->draining)
+        return AVERROR_EOF;
+
+    if (!pts || pts == AV_NOPTS_VALUE)
+        pts = avctx->reordered_opaque;
+
+    ret = mpp_packet_init(&mpkt, packet->data, packet->size);
+    if (ret != MPP_OK) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to init MPP packet (code = %d)\n", ret);
+        return AVERROR_UNKNOWN;
+    }
+
+    mpp_packet_set_pts(mpkt, pts);
+
+    ret = decoder->mpi->decode_put_packet(decoder->ctx, mpkt);
+    mpp_packet_deinit(&mpkt);
+
+    if (ret != MPP_OK) {
+        av_log(avctx, AV_LOG_DEBUG, "Buffer full\n");
+        return AVERROR(EAGAIN);
+    }
+
+    av_log(avctx, AV_LOG_DEBUG, "Wrote %d bytes to decoder\n", packet->size);
+    return 0;
+}
+
+static int rkmpp_send_eos(AVCodecContext *avctx)
+{
+    RKMPPDecodeContext *rk_context = avctx->priv_data;
+    RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+    MppPacket mpkt;
+    int ret;
+
+    ret = mpp_packet_init(&mpkt, NULL, 0);
+    if (ret != MPP_OK) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to init EOS packet (code = %d)\n", ret);
+        return AVERROR_UNKNOWN;
+    }
+
+    mpp_packet_set_eos(mpkt);
+
+    do {
+        ret = decoder->mpi->decode_put_packet(decoder->ctx, mpkt);
+    } while (ret != MPP_OK);
+    mpp_packet_deinit(&mpkt);
+
+    decoder->draining = 1;
+
+    return 0;
+}
+
 static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
     RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
-    int ret = MPP_NOK;
-    AVPacket pkt = {0};
-    RK_S32 usedslots, freeslots;
-
-    if (!decoder->eos_reached) {
-        // we get the available slots in decoder
-        ret = decoder->mpi->control(decoder->ctx, MPP_DEC_GET_STREAM_COUNT, &usedslots);
-        if (ret != MPP_OK) {
-            av_log(avctx, AV_LOG_ERROR, "Failed to get decoder used slots (code = %d).\n", ret);
-            return ret;
-        }
+    AVPacket *packet = &decoder->packet;
+    int ret;
 
-        freeslots = INPUT_MAX_PACKETS - usedslots;
-        if (freeslots > 0) {
-            ret = ff_decode_get_packet(avctx, &pkt);
-            if (ret < 0 && ret != AVERROR_EOF) {
+    // no more frames after EOS
+    if (decoder->eos)
+        return AVERROR_EOF;
+
+    // draining remain frames
+    if (decoder->draining)
+        return rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_BLOCK);
+
+    while (1) {
+        if (!packet->size) {
+            ret = ff_decode_get_packet(avctx, packet);
+            if (ret == AVERROR_EOF) {
+                av_log(avctx, AV_LOG_DEBUG, "End of stream.\n");
+                // send EOS and start draining
+                rkmpp_send_eos(avctx);
+                return rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_BLOCK);
+            } else if (ret == AVERROR(EAGAIN)) {
+                // not blocking so that we can feed new data ASAP
+                return rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_NON_BLOCK);
+            } else if (ret < 0) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to get packet (code = %d)\n", ret);
                 return ret;
             }
-
-            ret = rkmpp_send_packet(avctx, &pkt);
-            av_packet_unref(&pkt);
-
-            if (ret < 0) {
-                av_log(avctx, AV_LOG_ERROR, "Failed to send packet to decoder (code = %d)\n", ret);
+        } else {
+            // send pending data to decoder
+            ret = rkmpp_send_packet(avctx, packet);
+            if (ret == AVERROR(EAGAIN)) {
+                // some streams might need more packets to start returning frames
+                ret = rkmpp_get_frame(avctx, frame, 1);
+                if (ret != AVERROR(EAGAIN))
+                    return ret;
+            } else if (ret < 0) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to send data (code = %d)\n", ret);
                 return ret;
+            } else {
+                av_packet_unref(packet);
+                packet->size = 0;
             }
         }
-
-        // make sure we keep decoder full
-        if (freeslots > 1)
-            return AVERROR(EAGAIN);
     }
-
-    return rkmpp_retrieve_frame(avctx, frame);
 }
 
 static void rkmpp_flush(AVCodecContext *avctx)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
     RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
-    int ret = MPP_NOK;
 
     av_log(avctx, AV_LOG_DEBUG, "Flush.\n");
 
-    ret = decoder->mpi->reset(decoder->ctx);
-    if (ret == MPP_OK) {
-        decoder->first_packet = 1;
-        decoder->eos_reached = 0;
-    } else
-        av_log(avctx, AV_LOG_ERROR, "Failed to reset MPI (code = %d)\n", ret);
+    decoder->mpi->reset(decoder->ctx);
+
+    rkmpp_prepare_decoder(avctx);
+
+    decoder->eos = 0;
+    decoder->draining = 0;
+
+    av_packet_unref(&decoder->packet);
 }
 
 static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
-- 
2.40.0


From 3f94c029c3eeca764c63e32435e8ca8241a87dfc Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Fri, 21 May 2021 04:23:36 +0800
Subject: [PATCH 05/18] HACK: avcodec/rkmppdec: Force aligning coded width and
 height to 64

The chromium would try to align planes' width and height to 32, which
might break the plane buffers' contiguous required by RGA.

Passing a 64-aligned coded width and height to avoid that.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 libavcodec/rkmppdec.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index 7c28378120..bae3ca6cb5 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -309,6 +309,11 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
         avctx->width = mpp_frame_get_width(mppframe);
         avctx->height = mpp_frame_get_height(mppframe);
 
+        // chromium would align planes' width and height to 32, adding this
+        // hack to avoid breaking the plane buffers' contiguous.
+        avctx->coded_width = FFALIGN(avctx->width, 64);
+        avctx->coded_height = FFALIGN(avctx->height, 64);
+
         decoder->mpi->control(decoder->ctx, MPP_DEC_SET_FRAME_INFO, (MppParam) mppframe);
         decoder->mpi->control(decoder->ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
 
-- 
2.40.0


From 804808de6c6af583b71526ff9e11196e1515e542 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Thu, 20 May 2021 10:20:17 +0800
Subject: [PATCH 06/18] HACK: avcodec/rkmppdec: Support outputing YUV420P

Lots of users support YUV420P format rather than DRM_PRIME.

Support RGA accelerated format conversion.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 configure             |   7 ++-
 libavcodec/rkmppdec.c | 120 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 125 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 89af70d72f..9e08481e11 100755
--- a/configure
+++ b/configure
@@ -345,6 +345,7 @@ External library support:
   --enable-omx             enable OpenMAX IL code [no]
   --enable-omx-rpi         enable OpenMAX IL code for Raspberry Pi [no]
   --enable-rkmpp           enable Rockchip Media Process Platform code [no]
+  --enable-librga          enable Rockchip RGA 2D accel via librga [autodetect]
   --disable-v4l2-m2m       disable V4L2 mem2mem code [autodetect]
   --disable-vaapi          disable Video Acceleration API (mainly Unix/Intel) code [autodetect]
   --disable-vdpau          disable Nvidia Video Decode and Presentation API for Unix code [autodetect]
@@ -1848,6 +1849,7 @@ HWACCEL_AUTODETECT_LIBRARY_LIST="
     videotoolbox
     v4l2_m2m
     xvmc
+    librga
 "
 
 # catchall list of things that require external libs to link
@@ -6539,10 +6541,13 @@ enabled openssl           && { check_pkg_config openssl openssl openssl/ssl.h OP
                                check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 ||
                                die "ERROR: openssl not found"; }
 enabled pocketsphinx      && require_pkg_config pocketsphinx pocketsphinx pocketsphinx/pocketsphinx.h ps_init
+enabled librga            && check_lib librga rga/RgaApi.h c_RkRgaInit -lrga && prepend rkmpp_deps "librga"
 enabled rkmpp             && { require_pkg_config rkmpp rockchip_mpp  rockchip/rk_mpi.h mpp_create &&
                                require_pkg_config rockchip_mpp "rockchip_mpp >= 1.3.7" rockchip/rk_mpi.h mpp_create &&
                                { enabled libdrm ||
-                                 die "ERROR: rkmpp requires --enable-libdrm"; }
+                                 die "ERROR: rkmpp requires --enable-libdrm"; } &&
+                               { enabled librga ||
+                                 warn "using rkmpp without librga"; }
                              }
 enabled vapoursynth       && require_pkg_config vapoursynth "vapoursynth-script >= 42" VSScript.h vsscript_init
 
diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index bae3ca6cb5..c621e687e0 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -38,6 +38,11 @@
 #include "libavutil/imgutils.h"
 #include "libavutil/log.h"
 
+#if CONFIG_LIBRGA
+#include <rga/rga.h>
+#include <rga/RgaApi.h>
+#endif
+
 typedef struct {
     MppCtx ctx;
     MppApi *mpi;
@@ -83,6 +88,17 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
     }
 }
 
+#if CONFIG_LIBRGA
+static uint32_t rkmpp_get_rgaformat(MppFrameFormat mppformat)
+{
+    switch (mppformat) {
+    case MPP_FMT_YUV420SP:          return RK_FORMAT_YCbCr_420_SP;
+    case MPP_FMT_YUV420SP_10BIT:    return RK_FORMAT_YCbCr_420_SP_10B;
+    default:                        return RK_FORMAT_UNKNOWN;
+    }
+}
+#endif
+
 static int rkmpp_close_decoder(AVCodecContext *avctx)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
@@ -142,7 +158,7 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
     MppCodingType codectype = MPP_VIDEO_CodingUnused;
     int ret;
 
-    avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME;
+    avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
 
     // create a decoder and a ref to it
     decoder = av_mallocz(sizeof(RKMPPDecoder));
@@ -248,6 +264,95 @@ static void rkmpp_release_frame(void *opaque, uint8_t *data)
     av_free(desc);
 }
 
+static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame,
+                               MppFrame mppframe, MppBuffer buffer)
+{
+    char *src = mpp_buffer_get_ptr(buffer);
+    char *dst_y = frame->data[0];
+    char *dst_u = frame->data[1];
+    char *dst_v = frame->data[2];
+#if CONFIG_LIBRGA
+    RgaSURF_FORMAT format = rkmpp_get_rgaformat(mpp_frame_get_fmt(mppframe));
+#endif
+    int width = mpp_frame_get_width(mppframe);
+    int height = mpp_frame_get_height(mppframe);
+    int hstride = mpp_frame_get_hor_stride(mppframe);
+    int vstride = mpp_frame_get_ver_stride(mppframe);
+    int y_pitch = frame->linesize[0];
+    int u_pitch = frame->linesize[1];
+    int v_pitch = frame->linesize[2];
+    int i, j;
+
+#if CONFIG_LIBRGA
+    rga_info_t src_info = {0};
+    rga_info_t dst_info = {0};
+    int dst_height = (dst_u - dst_y) / y_pitch;
+
+    static int rga_supported = 1;
+    static int rga_inited = 0;
+
+    if (!rga_supported)
+        goto bail;
+
+    if (!rga_inited) {
+        if (c_RkRgaInit() < 0) {
+            rga_supported = 0;
+            av_log(avctx, AV_LOG_WARNING, "RGA not available\n");
+            goto bail;
+        }
+        rga_inited = 1;
+    }
+
+    if (format == RK_FORMAT_UNKNOWN)
+        goto bail;
+
+    if (u_pitch != y_pitch / 2 || v_pitch != y_pitch / 2 ||
+        dst_u != dst_y + y_pitch * dst_height ||
+        dst_v != dst_u + u_pitch * dst_height / 2)
+        goto bail;
+
+    src_info.fd = mpp_buffer_get_fd(buffer);
+    src_info.mmuFlag = 1;
+    rga_set_rect(&src_info.rect, 0, 0, width, height, hstride, vstride,
+                 format);
+
+    dst_info.virAddr = dst_y;
+    dst_info.mmuFlag = 1;
+    rga_set_rect(&dst_info.rect, 0, 0, frame->width, frame->height,
+                 y_pitch, dst_height, RK_FORMAT_YCbCr_420_P);
+
+    if (c_RkRgaBlit(&src_info, &dst_info, NULL) < 0)
+        goto bail;
+
+    return 0;
+
+bail:
+#endif
+    if (mpp_frame_get_fmt(mppframe) != MPP_FMT_YUV420SP) {
+        av_log(avctx, AV_LOG_WARNING, "Unable to convert\n");
+        return -1;
+    }
+
+    av_log(avctx, AV_LOG_WARNING, "Doing slow software conversion\n");
+
+    for (i = 0; i < frame->height; i++)
+        memcpy(dst_y + i * y_pitch, src + i * hstride, frame->width);
+
+    src += hstride * vstride;
+
+    for (i = 0; i < frame->height / 2; i++) {
+        for (j = 0; j < frame->width; j++) {
+            dst_u[j] = src[2 * j + 0];
+            dst_v[j] = src[2 * j + 1];
+        }
+        dst_u += u_pitch;
+        dst_v += v_pitch;
+        src += hstride;
+    }
+
+    return 0;
+}
+
 static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
@@ -355,6 +460,16 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
     frame->format           = avctx->pix_fmt;
     frame->width            = mpp_frame_get_width(mppframe);
     frame->height           = mpp_frame_get_height(mppframe);
+
+    if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) {
+        ret = ff_get_buffer(avctx, frame, 0);
+        if (ret < 0)
+            goto out;
+
+        ret = rkmpp_convert_frame(avctx, frame, mppframe, buffer);
+        goto out;
+    }
+
     frame->pts              = mpp_frame_get_pts(mppframe);
 #if FF_API_PKT_PTS
     FF_DISABLE_DEPRECATION_WARNINGS;
@@ -427,6 +542,7 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
 
     return 0;
 
+out:
 fail:
     if (mppframe)
         mpp_frame_deinit(&mppframe);
@@ -571,6 +687,7 @@ static void rkmpp_flush(AVCodecContext *avctx)
 
 static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
     HW_CONFIG_INTERNAL(DRM_PRIME),
+    HW_CONFIG_INTERNAL(YUV420P),
     NULL
 };
 
@@ -595,6 +712,7 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
         .priv_class     = &rkmpp_##NAME##_dec_class, \
         .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
         .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \
+                                                         AV_PIX_FMT_YUV420P, \
                                                          AV_PIX_FMT_NONE}, \
         .hw_configs     = rkmpp_hw_configs, \
         .bsfs           = BSFS, \
-- 
2.40.0


From ad6f4d3518eea4795f457b81d44d27da943be982 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Mon, 27 Sep 2021 10:20:54 +0800
Subject: [PATCH 07/18] avcodec/rkmppdec: Support logging fps

Set env FFMPEG_RKMPP_LOG_FPS=1 to enable it.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 libavcodec/rkmppdec.c | 46 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index c621e687e0..82834c27a6 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -25,6 +25,7 @@
 #include <rockchip/rk_mpi.h>
 #include <time.h>
 #include <unistd.h>
+#include <sys/time.h>
 
 #include "avcodec.h"
 #include "decode.h"
@@ -43,6 +44,8 @@
 #include <rga/RgaApi.h>
 #endif
 
+#define FPS_UPDATE_INTERVAL     120
+
 typedef struct {
     MppCtx ctx;
     MppApi *mpi;
@@ -54,6 +57,11 @@ typedef struct {
     AVPacket packet;
     AVBufferRef *frames_ref;
     AVBufferRef *device_ref;
+
+    char print_fps;
+
+    uint64_t last_fps_time;
+    uint64_t frames;
 } RKMPPDecoder;
 
 typedef struct {
@@ -156,6 +164,7 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
     RKMPPDecodeContext *rk_context = avctx->priv_data;
     RKMPPDecoder *decoder = NULL;
     MppCodingType codectype = MPP_VIDEO_CodingUnused;
+    char *env;
     int ret;
 
     avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
@@ -167,6 +176,10 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
         goto fail;
     }
 
+    env = getenv("FFMPEG_RKMPP_LOG_FPS");
+    if (env != NULL)
+        decoder->print_fps = !!atoi(env);
+
     rk_context->decoder_ref = av_buffer_create((uint8_t *)decoder, sizeof(*decoder), rkmpp_release_decoder,
                                                NULL, AV_BUFFER_FLAG_READONLY);
     if (!rk_context->decoder_ref) {
@@ -353,6 +366,36 @@ bail:
     return 0;
 }
 
+static void rkmpp_update_fps(AVCodecContext *avctx)
+{
+    RKMPPDecodeContext *rk_context = avctx->priv_data;
+    RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+    struct timeval tv;
+    uint64_t curr_time;
+    float fps;
+
+    if (!decoder->print_fps)
+        return;
+
+    if (!decoder->last_fps_time) {
+        gettimeofday(&tv, NULL);
+        decoder->last_fps_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+    }
+
+    if (++decoder->frames % FPS_UPDATE_INTERVAL)
+        return;
+
+    gettimeofday(&tv, NULL);
+    curr_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+
+    fps = 1000.0f * FPS_UPDATE_INTERVAL / (curr_time - decoder->last_fps_time);
+    decoder->last_fps_time = curr_time;
+
+    av_log(avctx, AV_LOG_INFO,
+           "[FFMPEG RKMPP] FPS: %6.1f || Frames: %" PRIu64 "\n",
+           fps, decoder->frames);
+}
+
 static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
@@ -456,6 +499,8 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
         goto fail;
     }
 
+    rkmpp_update_fps(avctx);
+
     // setup general frame fields
     frame->format           = avctx->pix_fmt;
     frame->width            = mpp_frame_get_width(mppframe);
@@ -681,6 +726,7 @@ static void rkmpp_flush(AVCodecContext *avctx)
 
     decoder->eos = 0;
     decoder->draining = 0;
+    decoder->last_fps_time = decoder->frames = 0;
 
     av_packet_unref(&decoder->packet);
 }
-- 
2.40.0


From 64a938f131b053a736d1158069300813cf2d16cc Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Thu, 5 Jan 2023 22:41:48 +0100
Subject: [PATCH 08/18] HACK: libavcodec & rkmppdec: Add
 FF_CODEC_CAP_CONTIGUOUS_BUFFERS

Add FF_CODEC_CAP_CONTIGUOUS_BUFFERS to alloc contiguous buffers.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 libavcodec/decode.c   | 23 +++++++++++++++++++++++
 libavcodec/internal.h |  4 ++++
 libavcodec/rkmppdec.c | 19 ++++++++++---------
 3 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 936e5d63da..dfd9ed656d 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -1549,6 +1549,14 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
 
         for (i = 0; i < 4; i++) {
             pool->linesize[i] = linesize[i];
+
+            if (avctx->codec->caps_internal & FF_CODEC_CAP_CONTIGUOUS_BUFFERS) {
+                if (!i)
+                    size[0] += size[1] + size[2] + size[3];
+                else
+                    continue;
+            }
+
             if (size[i]) {
                 if (size[i] > INT_MAX - (16 + STRIDE_ALIGN - 1)) {
                     ret = AVERROR(EINVAL);
@@ -1675,6 +1683,21 @@ static int video_get_buffer(AVCodecContext *s, AVFrame *pic)
 
         pic->data[i] = pic->buf[i]->data;
     }
+
+    if (s->codec->caps_internal & FF_CODEC_CAP_CONTIGUOUS_BUFFERS) {
+        int size;
+
+        for (i = 1; i < 4; i++) {
+            pic->linesize[i] = pool->linesize[i];
+            av_buffer_unref(pic->buf[i]);
+        }
+
+        size = av_image_fill_pointers(pic->data, pic->format, pic->height,
+                                      pic->buf[0]->data, pic->linesize);
+        if (size < 0 || size > pic->buf[0]->size)
+            goto fail;
+    }
+
     for (; i < AV_NUM_DATA_POINTERS; i++) {
         pic->data[i] = NULL;
         pic->linesize[i] = 0;
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index d889c1883e..47e6a1d13b 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -89,6 +89,10 @@
  */
 #define FF_CODEC_TAGS_END -1
 
+/**
+ * The decoder requires contiguous buffers.
+ */
+#define FF_CODEC_CAP_CONTIGUOUS_BUFFERS     (1 << 31)
 
 #ifdef TRACE
 #   define ff_tlog(ctx, ...) av_log(ctx, AV_LOG_TRACE, __VA_ARGS__)
diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index 82834c27a6..a05c77977d 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -501,20 +501,15 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
 
     rkmpp_update_fps(avctx);
 
-    // setup general frame fields
-    frame->format           = avctx->pix_fmt;
-    frame->width            = mpp_frame_get_width(mppframe);
-    frame->height           = mpp_frame_get_height(mppframe);
-
     if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) {
         ret = ff_get_buffer(avctx, frame, 0);
         if (ret < 0)
             goto out;
-
-        ret = rkmpp_convert_frame(avctx, frame, mppframe, buffer);
-        goto out;
     }
-
+    // setup general frame fields
+    frame->format           = avctx->pix_fmt;
+    frame->width            = mpp_frame_get_width(mppframe);
+    frame->height           = mpp_frame_get_height(mppframe);
     frame->pts              = mpp_frame_get_pts(mppframe);
 #if FF_API_PKT_PTS
     FF_DISABLE_DEPRECATION_WARNINGS;
@@ -531,6 +526,11 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
     frame->interlaced_frame = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED);
     frame->top_field_first  = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST);
 
+    if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) {
+        ret = rkmpp_convert_frame(avctx, frame, mppframe, buffer);
+        goto out;
+    }
+
     mppformat = mpp_frame_get_fmt(mppframe);
     drmformat = rkmpp_get_frameformat(mppformat);
 
@@ -757,6 +757,7 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
         .flush          = rkmpp_flush, \
         .priv_class     = &rkmpp_##NAME##_dec_class, \
         .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
+        .caps_internal  = FF_CODEC_CAP_CONTIGUOUS_BUFFERS, \
         .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \
                                                          AV_PIX_FMT_YUV420P, \
                                                          AV_PIX_FMT_NONE}, \
-- 
2.40.0


From ff895c90cca06ec9e0235d5aa06c25eaeb4b9f3f Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Mon, 13 Dec 2021 15:44:43 +0800
Subject: [PATCH 09/18] HACK: avcodec/rkmppdec: Define DRM_FORMAT_NV12_10

DRM_FORMAT_NV12_10 is a downstream custom format for Rockchip.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 libavcodec/rkmppdec.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index a05c77977d..2aa3ee2a30 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -44,6 +44,10 @@
 #include <rga/RgaApi.h>
 #endif
 
+#ifndef DRM_FORMAT_NV12_10
+#define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '2')
+#endif
+
 #define FPS_UPDATE_INTERVAL     120
 
 typedef struct {
@@ -89,9 +93,7 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
 {
     switch (mppformat) {
     case MPP_FMT_YUV420SP:          return DRM_FORMAT_NV12;
-#ifdef DRM_FORMAT_NV12_10
     case MPP_FMT_YUV420SP_10BIT:    return DRM_FORMAT_NV12_10;
-#endif
     default:                        return 0;
     }
 }
-- 
2.40.0


From c36fb133a52a3b80b682b97b37b9e754de62eca0 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Wed, 15 Dec 2021 15:34:48 +0800
Subject: [PATCH 10/18] avcodec/rkmppdec: Support NV16

The MPP might output NV16 format.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 libavcodec/rkmppdec.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index 2aa3ee2a30..82288cad03 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -94,6 +94,17 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
     switch (mppformat) {
     case MPP_FMT_YUV420SP:          return DRM_FORMAT_NV12;
     case MPP_FMT_YUV420SP_10BIT:    return DRM_FORMAT_NV12_10;
+    case MPP_FMT_YUV422SP:          return DRM_FORMAT_NV16;
+    default:                        return 0;
+    }
+}
+
+static uint32_t rkmpp_get_avformat(MppFrameFormat mppformat)
+{
+    switch (mppformat) {
+    case MPP_FMT_YUV420SP:          return AV_PIX_FMT_NV12;
+    case MPP_FMT_YUV420SP_10BIT:    return AV_PIX_FMT_NONE;
+    case MPP_FMT_YUV422SP:          return AV_PIX_FMT_NV16;
     default:                        return 0;
     }
 }
@@ -104,6 +115,7 @@ static uint32_t rkmpp_get_rgaformat(MppFrameFormat mppformat)
     switch (mppformat) {
     case MPP_FMT_YUV420SP:          return RK_FORMAT_YCbCr_420_SP;
     case MPP_FMT_YUV420SP_10BIT:    return RK_FORMAT_YCbCr_420_SP_10B;
+    case MPP_FMT_YUV422SP:          return RK_FORMAT_YCbCr_422_SP;
     default:                        return RK_FORMAT_UNKNOWN;
     }
 }
@@ -476,11 +488,10 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
         }
 
         mppformat = mpp_frame_get_fmt(mppframe);
-        drmformat = rkmpp_get_frameformat(mppformat);
 
         hwframes = (AVHWFramesContext*)decoder->frames_ref->data;
         hwframes->format    = AV_PIX_FMT_DRM_PRIME;
-        hwframes->sw_format = drmformat == DRM_FORMAT_NV12 ? AV_PIX_FMT_NV12 : AV_PIX_FMT_NONE;
+        hwframes->sw_format = rkmpp_get_avformat(mppformat);
         hwframes->width     = avctx->width;
         hwframes->height    = avctx->height;
         ret = av_hwframe_ctx_init(decoder->frames_ref);
-- 
2.40.0


From 31cbeac7974485c9bbf55d155ebc742f87e98f11 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Wed, 23 Mar 2022 14:20:16 +0800
Subject: [PATCH 11/18] avcodec/rkmppdec: Support sync mode

Some people just don't know how to handle async APIs :(

Support sync mode by waiting for decode result after feeding any packets.

Set env "FFMPEG_RKMPP_SYNC" to enable it.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 libavcodec/rkmppdec.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index 82288cad03..c8b400e910 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -66,6 +66,8 @@ typedef struct {
 
     uint64_t last_fps_time;
     uint64_t frames;
+
+    char sync;
 } RKMPPDecoder;
 
 typedef struct {
@@ -170,6 +172,13 @@ static int rkmpp_prepare_decoder(AVCodecContext *avctx)
         if (ret < 0)
             return AVERROR_UNKNOWN;
     }
+
+    if (getenv("FFMPEG_RKMPP_SYNC")) {
+        // wait for decode result after feeding any packets
+        decoder->sync = 1;
+        ret = 1;
+        decoder->mpi->control(decoder->ctx, MPP_DEC_SET_IMMEDIATE_OUT, &ret);
+    }
     return 0;
 }
 
@@ -721,6 +730,10 @@ static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame)
             } else {
                 av_packet_unref(packet);
                 packet->size = 0;
+
+                // blocked waiting for decode result
+                if (decoder->sync)
+                    return rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_BLOCK);
             }
         }
     }
-- 
2.40.0


From 8eb641d7f655691086e9e1fa0a6d116be9af3e44 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Thu, 5 Jan 2023 23:04:45 +0100
Subject: [PATCH 12/18] avcodec/rkmppdec: Add H263/MPEG1/MPEG2/MPEG4

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 configure              | 4 ++++
 libavcodec/Makefile    | 4 ++++
 libavcodec/allcodecs.c | 4 ++++
 libavcodec/rkmppdec.c  | 8 ++++++++
 4 files changed, 20 insertions(+)

diff --git a/configure b/configure
index 9e08481e11..6e72375e09 100755
--- a/configure
+++ b/configure
@@ -3074,6 +3074,7 @@ ac3_mf_encoder_deps="mediafoundation"
 av1_cuvid_decoder_deps="cuvid CUVIDAV1PICPARAMS"
 h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m"
 h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m"
+h263_rkmpp_decoder_deps="rkmpp"
 h264_amf_encoder_deps="amf"
 h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser"
 h264_cuvid_decoder_deps="cuvid"
@@ -3119,6 +3120,7 @@ mjpeg_vaapi_encoder_select="cbs_jpeg jpegtables vaapi_encode"
 mp3_mf_encoder_deps="mediafoundation"
 mpeg1_cuvid_decoder_deps="cuvid"
 mpeg1_v4l2m2m_decoder_deps="v4l2_m2m mpeg1_v4l2_m2m"
+mpeg1_rkmpp_decoder_deps="rkmpp"
 mpeg2_crystalhd_decoder_select="crystalhd"
 mpeg2_cuvid_decoder_deps="cuvid"
 mpeg2_mmal_decoder_deps="mmal"
@@ -3127,6 +3129,7 @@ mpeg2_qsv_decoder_select="qsvdec"
 mpeg2_qsv_encoder_select="qsvenc"
 mpeg2_vaapi_encoder_select="cbs_mpeg2 vaapi_encode"
 mpeg2_v4l2m2m_decoder_deps="v4l2_m2m mpeg2_v4l2_m2m"
+mpeg2_rkmpp_decoder_deps="rkmpp"
 mpeg4_crystalhd_decoder_select="crystalhd"
 mpeg4_cuvid_decoder_deps="cuvid"
 mpeg4_mediacodec_decoder_deps="mediacodec"
@@ -3134,6 +3137,7 @@ mpeg4_mmal_decoder_deps="mmal"
 mpeg4_omx_encoder_deps="omx"
 mpeg4_v4l2m2m_decoder_deps="v4l2_m2m mpeg4_v4l2_m2m"
 mpeg4_v4l2m2m_encoder_deps="v4l2_m2m mpeg4_v4l2_m2m"
+mpeg4_rkmpp_decoder_deps="rkmpp"
 msmpeg4_crystalhd_decoder_select="crystalhd"
 nvenc_h264_encoder_select="h264_nvenc_encoder"
 nvenc_hevc_encoder_select="hevc_nvenc_encoder"
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index b3d284d7d0..345b6a5816 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -364,6 +364,7 @@ OBJS-$(CONFIG_H263_ENCODER)            += mpeg4video.o  \
                                           h263.o ituh263enc.o h263data.o
 OBJS-$(CONFIG_H263_V4L2M2M_DECODER)    += v4l2_m2m_dec.o
 OBJS-$(CONFIG_H263_V4L2M2M_ENCODER)    += v4l2_m2m_enc.o
+OBJS-$(CONFIG_H263_RKMPP_DECODER)      += rkmppdec.o
 OBJS-$(CONFIG_H264_DECODER)            += h264dec.o h264_cabac.o h264_cavlc.o \
                                           h264_direct.o h264_loopfilter.o  \
                                           h264_mb.o h264_picture.o \
@@ -488,6 +489,7 @@ OBJS-$(CONFIG_MPEG1VIDEO_DECODER)      += mpeg12dec.o mpeg12.o mpeg12data.o
 OBJS-$(CONFIG_MPEG1VIDEO_ENCODER)      += mpeg12enc.o mpeg12.o
 OBJS-$(CONFIG_MPEG1_CUVID_DECODER)     += cuviddec.o
 OBJS-$(CONFIG_MPEG1_V4L2M2M_DECODER)   += v4l2_m2m_dec.o
+OBJS-$(CONFIG_MPEG1_RKMPP_DECODER)     += rkmppdec.o
 OBJS-$(CONFIG_MPEG2_MMAL_DECODER)      += mmaldec.o
 OBJS-$(CONFIG_MPEG2_QSV_DECODER)       += qsvdec.o
 OBJS-$(CONFIG_MPEG2_QSV_ENCODER)       += qsvenc_mpeg2.o
@@ -497,6 +499,7 @@ OBJS-$(CONFIG_MPEG2_CUVID_DECODER)     += cuviddec.o
 OBJS-$(CONFIG_MPEG2_MEDIACODEC_DECODER) += mediacodecdec.o
 OBJS-$(CONFIG_MPEG2_VAAPI_ENCODER)     += vaapi_encode_mpeg2.o
 OBJS-$(CONFIG_MPEG2_V4L2M2M_DECODER)   += v4l2_m2m_dec.o
+OBJS-$(CONFIG_MPEG2_RKMPP_DECODER)     += rkmppdec.o
 OBJS-$(CONFIG_MPEG4_DECODER)           += xvididct.o
 OBJS-$(CONFIG_MPEG4_ENCODER)           += mpeg4videoenc.o
 OBJS-$(CONFIG_MPEG4_CUVID_DECODER)     += cuviddec.o
@@ -504,6 +507,7 @@ OBJS-$(CONFIG_MPEG4_MEDIACODEC_DECODER) += mediacodecdec.o
 OBJS-$(CONFIG_MPEG4_OMX_ENCODER)       += omx.o
 OBJS-$(CONFIG_MPEG4_V4L2M2M_DECODER)   += v4l2_m2m_dec.o
 OBJS-$(CONFIG_MPEG4_V4L2M2M_ENCODER)   += v4l2_m2m_enc.o
+OBJS-$(CONFIG_MPEG4_RKMPP_DECODER)     += rkmppdec.o
 OBJS-$(CONFIG_MPL2_DECODER)            += mpl2dec.o ass.o
 OBJS-$(CONFIG_MSA1_DECODER)            += mss3.o
 OBJS-$(CONFIG_MSCC_DECODER)            += mscc.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 2e9a3581de..5b2d8abe80 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -140,6 +140,7 @@ extern AVCodec ff_h263_decoder;
 extern AVCodec ff_h263i_decoder;
 extern AVCodec ff_h263p_encoder;
 extern AVCodec ff_h263p_decoder;
+extern AVCodec ff_h263_rkmpp_decoder;
 extern AVCodec ff_h263_v4l2m2m_decoder;
 extern AVCodec ff_h264_decoder;
 extern AVCodec ff_h264_crystalhd_decoder;
@@ -199,11 +200,14 @@ extern AVCodec ff_mpeg2video_decoder;
 extern AVCodec ff_mpeg4_encoder;
 extern AVCodec ff_mpeg4_decoder;
 extern AVCodec ff_mpeg4_crystalhd_decoder;
+extern AVCodec ff_mpeg4_rkmpp_decoder;
 extern AVCodec ff_mpeg4_v4l2m2m_decoder;
 extern AVCodec ff_mpeg4_mmal_decoder;
 extern AVCodec ff_mpegvideo_decoder;
+extern AVCodec ff_mpeg1_rkmpp_decoder;
 extern AVCodec ff_mpeg1_v4l2m2m_decoder;
 extern AVCodec ff_mpeg2_mmal_decoder;
+extern AVCodec ff_mpeg2_rkmpp_decoder;
 extern AVCodec ff_mpeg2_crystalhd_decoder;
 extern AVCodec ff_mpeg2_v4l2m2m_decoder;
 extern AVCodec ff_mpeg2_qsv_decoder;
diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index c8b400e910..79baab932d 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -83,10 +83,14 @@ typedef struct {
 static MppCodingType rkmpp_get_codingtype(AVCodecContext *avctx)
 {
     switch (avctx->codec_id) {
+    case AV_CODEC_ID_H263:          return MPP_VIDEO_CodingH263;
     case AV_CODEC_ID_H264:          return MPP_VIDEO_CodingAVC;
     case AV_CODEC_ID_HEVC:          return MPP_VIDEO_CodingHEVC;
     case AV_CODEC_ID_VP8:           return MPP_VIDEO_CodingVP8;
     case AV_CODEC_ID_VP9:           return MPP_VIDEO_CodingVP9;
+    case AV_CODEC_ID_MPEG1VIDEO:    /* fallthrough */
+    case AV_CODEC_ID_MPEG2VIDEO:    return MPP_VIDEO_CodingMPEG2;
+    case AV_CODEC_ID_MPEG4:         return MPP_VIDEO_CodingMPEG4;
     default:                        return MPP_VIDEO_CodingUnused;
     }
 }
@@ -792,7 +796,11 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
         .wrapper_name   = "rkmpp", \
     };
 
+RKMPP_DEC(h263,  AV_CODEC_ID_H263,          NULL)
 RKMPP_DEC(h264,  AV_CODEC_ID_H264,          "h264_mp4toannexb")
 RKMPP_DEC(hevc,  AV_CODEC_ID_HEVC,          "hevc_mp4toannexb")
 RKMPP_DEC(vp8,   AV_CODEC_ID_VP8,           NULL)
 RKMPP_DEC(vp9,   AV_CODEC_ID_VP9,           NULL)
+RKMPP_DEC(mpeg1, AV_CODEC_ID_MPEG1VIDEO,    NULL)
+RKMPP_DEC(mpeg2, AV_CODEC_ID_MPEG2VIDEO,    NULL)
+RKMPP_DEC(mpeg4, AV_CODEC_ID_MPEG4,         "mpeg4_unpack_bframes")
-- 
2.40.0


From fadc27c2b4bfddb869c1df32d2e6fe7ecb4cb3e8 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Fri, 6 Jan 2023 20:39:23 +0100
Subject: [PATCH 13/18] allow nv15 and allow probing

---
 libavcodec/rkmppdec.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index 79baab932d..93c426eeb3 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -45,7 +45,7 @@
 #endif
 
 #ifndef DRM_FORMAT_NV12_10
-#define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '2')
+#define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '5')
 #endif
 
 #define FPS_UPDATE_INTERVAL     120
@@ -786,7 +786,7 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
         .receive_frame  = rkmpp_receive_frame, \
         .flush          = rkmpp_flush, \
         .priv_class     = &rkmpp_##NAME##_dec_class, \
-        .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
+        .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \
         .caps_internal  = FF_CODEC_CAP_CONTIGUOUS_BUFFERS, \
         .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \
                                                          AV_PIX_FMT_YUV420P, \
-- 
2.40.0


From c1684a12173449e5d0792a2a6fe9b9fabed9aa21 Mon Sep 17 00:00:00 2001
From: boogie <boogiepop@gmx.com>
Date: Fri, 6 Jan 2023 21:36:04 +0100
Subject: [PATCH 14/18] priotrize the rkmpp variants first

---
 libavcodec/allcodecs.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 5b2d8abe80..409e7f33e4 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -135,25 +135,25 @@ extern AVCodec ff_gif_encoder;
 extern AVCodec ff_gif_decoder;
 extern AVCodec ff_h261_encoder;
 extern AVCodec ff_h261_decoder;
+extern AVCodec ff_h263_rkmpp_decoder;
 extern AVCodec ff_h263_encoder;
 extern AVCodec ff_h263_decoder;
 extern AVCodec ff_h263i_decoder;
 extern AVCodec ff_h263p_encoder;
 extern AVCodec ff_h263p_decoder;
-extern AVCodec ff_h263_rkmpp_decoder;
 extern AVCodec ff_h263_v4l2m2m_decoder;
+extern AVCodec ff_h264_rkmpp_decoder;
 extern AVCodec ff_h264_decoder;
 extern AVCodec ff_h264_crystalhd_decoder;
 extern AVCodec ff_h264_v4l2m2m_decoder;
 extern AVCodec ff_h264_mediacodec_decoder;
 extern AVCodec ff_h264_mmal_decoder;
 extern AVCodec ff_h264_qsv_decoder;
-extern AVCodec ff_h264_rkmpp_decoder;
 extern AVCodec ff_hap_encoder;
 extern AVCodec ff_hap_decoder;
+extern AVCodec ff_hevc_rkmpp_decoder;
 extern AVCodec ff_hevc_decoder;
 extern AVCodec ff_hevc_qsv_decoder;
-extern AVCodec ff_hevc_rkmpp_decoder;
 extern AVCodec ff_hevc_v4l2m2m_decoder;
 extern AVCodec ff_hnm4_video_decoder;
 extern AVCodec ff_hq_hqa_decoder;
@@ -193,21 +193,21 @@ extern AVCodec ff_mjpegb_decoder;
 extern AVCodec ff_mmvideo_decoder;
 extern AVCodec ff_mobiclip_decoder;
 extern AVCodec ff_motionpixels_decoder;
+extern AVCodec ff_mpeg1_rkmpp_decoder;
 extern AVCodec ff_mpeg1video_encoder;
 extern AVCodec ff_mpeg1video_decoder;
 extern AVCodec ff_mpeg2video_encoder;
 extern AVCodec ff_mpeg2video_decoder;
+extern AVCodec ff_mpeg4_rkmpp_decoder;
 extern AVCodec ff_mpeg4_encoder;
 extern AVCodec ff_mpeg4_decoder;
 extern AVCodec ff_mpeg4_crystalhd_decoder;
-extern AVCodec ff_mpeg4_rkmpp_decoder;
 extern AVCodec ff_mpeg4_v4l2m2m_decoder;
 extern AVCodec ff_mpeg4_mmal_decoder;
 extern AVCodec ff_mpegvideo_decoder;
-extern AVCodec ff_mpeg1_rkmpp_decoder;
 extern AVCodec ff_mpeg1_v4l2m2m_decoder;
-extern AVCodec ff_mpeg2_mmal_decoder;
 extern AVCodec ff_mpeg2_rkmpp_decoder;
+extern AVCodec ff_mpeg2_mmal_decoder;
 extern AVCodec ff_mpeg2_crystalhd_decoder;
 extern AVCodec ff_mpeg2_v4l2m2m_decoder;
 extern AVCodec ff_mpeg2_qsv_decoder;
@@ -360,11 +360,11 @@ extern AVCodec ff_vp6_decoder;
 extern AVCodec ff_vp6a_decoder;
 extern AVCodec ff_vp6f_decoder;
 extern AVCodec ff_vp7_decoder;
-extern AVCodec ff_vp8_decoder;
 extern AVCodec ff_vp8_rkmpp_decoder;
+extern AVCodec ff_vp8_decoder;
 extern AVCodec ff_vp8_v4l2m2m_decoder;
-extern AVCodec ff_vp9_decoder;
 extern AVCodec ff_vp9_rkmpp_decoder;
+extern AVCodec ff_vp9_decoder;
 extern AVCodec ff_vp9_v4l2m2m_decoder;
 extern AVCodec ff_vqa_decoder;
 extern AVCodec ff_webp_decoder;
-- 
2.40.0


From 76ec717e3fa8d21101cb9442c5a7c658a0f08f27 Mon Sep 17 00:00:00 2001
From: icecream95 <the.real.icecream95@gmail.com>
Date: Fri, 13 Jan 2023 22:27:01 +0100
Subject: [PATCH 15/18] rkmpp: interface with kernel directly for rga and ditch
 librga

credit goes to icecream95: https://gitlab.com/-/snippets/2460396
---
 libavcodec/rga.h      | 574 ++++++++++++++++++++++++++++++++++++++++++
 libavcodec/rkmppdec.c | 272 ++++++++++++++++----
 2 files changed, 803 insertions(+), 43 deletions(-)
 create mode 100644 libavcodec/rga.h

diff --git a/libavcodec/rga.h b/libavcodec/rga.h
new file mode 100644
index 0000000000..9595558de0
--- /dev/null
+++ b/libavcodec/rga.h
@@ -0,0 +1,574 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _RGA_DRIVER_H_
+#define _RGA_DRIVER_H_
+
+/* Use 'r' as magic number */
+#define RGA_IOC_MAGIC		'r'
+#define RGA_IOW(nr, type)	_IOW(RGA_IOC_MAGIC, nr, type)
+#define RGA_IOR(nr, type)	_IOR(RGA_IOC_MAGIC, nr, type)
+#define RGA_IOWR(nr, type)	_IOWR(RGA_IOC_MAGIC, nr, type)
+
+#define RGA_IOC_GET_DRVIER_VERSION	RGA_IOR(0x1, struct rga_version_t)
+#define RGA_IOC_GET_HW_VERSION		RGA_IOR(0x2, struct rga_hw_versions_t)
+#define RGA_IOC_IMPORT_BUFFER		RGA_IOWR(0x3, struct rga_buffer_pool)
+#define RGA_IOC_RELEASE_BUFFER		RGA_IOW(0x4, struct rga_buffer_pool)
+#define RGA_IOC_REQUEST_CREATE		RGA_IOR(0x5, uint32_t)
+#define RGA_IOC_REQUEST_SUBMIT		RGA_IOWR(0x6, struct rga_user_request)
+#define RGA_IOC_REQUEST_CONFIG		RGA_IOWR(0x7, struct rga_user_request)
+#define RGA_IOC_REQUEST_CANCEL		RGA_IOWR(0x8, uint32_t)
+
+#define RGA_BLIT_SYNC			0x5017
+#define RGA_BLIT_ASYNC			0x5018
+#define RGA_FLUSH			0x5019
+#define RGA_GET_RESULT			0x501a
+#define RGA_GET_VERSION			0x501b
+#define RGA_CACHE_FLUSH			0x501c
+
+#define RGA2_GET_VERSION		0x601b
+#define RGA_IMPORT_DMA			0x601d
+#define RGA_RELEASE_DMA			0x601e
+
+#define RGA_TASK_NUM_MAX		50
+
+#define RGA_OUT_OF_RESOURCES		-10
+#define RGA_MALLOC_ERROR		-11
+
+#define SCALE_DOWN_LARGE		1
+#define SCALE_UP_LARGE			1
+
+#define RGA_BUFFER_POOL_SIZE_MAX 40
+
+#define RGA3_MAJOR_VERSION_MASK	 (0xF0000000)
+#define RGA3_MINOR_VERSION_MASK	 (0x0FF00000)
+#define RGA3_SVN_VERSION_MASK	 (0x000FFFFF)
+
+#define RGA2_MAJOR_VERSION_MASK	 (0xFF000000)
+#define RGA2_MINOR_VERSION_MASK	 (0x00F00000)
+#define RGA2_SVN_VERSION_MASK	 (0x000FFFFF)
+
+#define RGA_MODE_ROTATE_0	 (1<<0)
+#define RGA_MODE_ROTATE_90	 (1<<1)
+#define RGA_MODE_ROTATE_180	 (1<<2)
+#define RGA_MODE_ROTATE_270	 (1<<3)
+#define RGA_MODE_X_MIRROR	 (1<<4)
+#define RGA_MODE_Y_MIRROR	 (1<<5)
+
+#define RGA_MODE_CSC_BT601L	 (1<<0)
+#define RGA_MODE_CSC_BT601F	 (1<<1)
+#define RGA_MODE_CSC_BT709	 (1<<2)
+#define RGA_MODE_CSC_BT2020	 (1<<3)
+
+#define RGA_MODE_ROTATE_MASK (\
+		RGA_MODE_ROTATE_0 | \
+		RGA_MODE_ROTATE_90 | \
+		RGA_MODE_ROTATE_180 | \
+		RGA_MODE_ROTATE_270 | \
+		RGA_MODE_X_MIRROR | \
+		RGA_MODE_Y_MIRROR)
+
+enum rga_memory_type {
+	RGA_DMA_BUFFER = 0,
+	RGA_VIRTUAL_ADDRESS,
+	RGA_PHYSICAL_ADDRESS,
+	RGA_DMA_BUFFER_PTR,
+};
+
+enum rga_scale_up_mode {
+	RGA_SCALE_UP_NONE	= 0x0,
+	RGA_SCALE_UP_BIC	= 0x1,
+};
+
+enum rga_scale_down_mode {
+	RGA_SCALE_DOWN_NONE	= 0x0,
+	RGA_SCALE_DOWN_AVG	= 0x1,
+};
+
+/* RGA process mode enum */
+enum {
+	BITBLT_MODE			= 0x0,
+	COLOR_PALETTE_MODE		= 0x1,
+	COLOR_FILL_MODE			= 0x2,
+	/* used by rga2 */
+	UPDATE_PALETTE_TABLE_MODE	= 0x6,
+	UPDATE_PATTEN_BUF_MODE		= 0x7,
+}; /*render mode*/
+
+/* RGA rd_mode */
+enum {
+	RGA_RASTER_MODE			 = 0x1 << 0,
+	RGA_FBC_MODE			 = 0x1 << 1,
+	RGA_TILE_MODE			 = 0x1 << 2,
+};
+
+enum {
+	RGA_CONTEXT_NONE		= 0x0,
+	RGA_CONTEXT_SRC_FIX_ENABLE	= 0x1 << 0,
+	RGA_CONTEXT_SRC_CACHE_INFO	= 0x1 << 1,
+	RGA_CONTEXT_SRC_MASK		= RGA_CONTEXT_SRC_FIX_ENABLE |
+					  RGA_CONTEXT_SRC_CACHE_INFO,
+	RGA_CONTEXT_PAT_FIX_ENABLE	= 0x1 << 2,
+	RGA_CONTEXT_PAT_CACHE_INFO	= 0x1 << 3,
+	RGA_CONTEXT_PAT_MASK		= RGA_CONTEXT_PAT_FIX_ENABLE |
+					  RGA_CONTEXT_PAT_CACHE_INFO,
+	RGA_CONTEXT_DST_FIX_ENABLE	= 0x1 << 4,
+	RGA_CONTEXT_DST_CACHE_INFO	= 0x1 << 5,
+	RGA_CONTEXT_DST_MASK		= RGA_CONTEXT_DST_FIX_ENABLE |
+					  RGA_CONTEXT_DST_CACHE_INFO,
+};
+
+/* RGA feature */
+enum {
+	RGA_COLOR_FILL			= 0x1 << 0,
+	RGA_COLOR_PALETTE		= 0x1 << 1,
+	RGA_COLOR_KEY			= 0x1 << 2,
+	RGA_ROP_CALCULATE		= 0x1 << 3,
+	RGA_NN_QUANTIZE			= 0x1 << 4,
+	RGA_OSD_BLEND			= 0x1 << 5,
+	RGA_DITHER			= 0x1 << 6,
+	RGA_MOSAIC			= 0x1 << 7,
+	RGA_YIN_YOUT			= 0x1 << 8,
+	RGA_YUV_HDS			= 0x1 << 9,
+	RGA_YUV_VDS			= 0x1 << 10,
+	RGA_OSD				= 0x1 << 11,
+	RGA_PRE_INTR			= 0x1 << 12,
+};
+
+enum rga_surf_format {
+	RGA_FORMAT_RGBA_8888		= 0x0,
+	RGA_FORMAT_RGBX_8888		= 0x1,
+	RGA_FORMAT_RGB_888		= 0x2,
+	RGA_FORMAT_BGRA_8888		= 0x3,
+	RGA_FORMAT_RGB_565		= 0x4,
+	RGA_FORMAT_RGBA_5551		= 0x5,
+	RGA_FORMAT_RGBA_4444		= 0x6,
+	RGA_FORMAT_BGR_888		= 0x7,
+
+	RGA_FORMAT_YCbCr_422_SP		= 0x8,
+	RGA_FORMAT_YCbCr_422_P		= 0x9,
+	RGA_FORMAT_YCbCr_420_SP		= 0xa,
+	RGA_FORMAT_YCbCr_420_P		= 0xb,
+
+	RGA_FORMAT_YCrCb_422_SP		= 0xc,
+	RGA_FORMAT_YCrCb_422_P		= 0xd,
+	RGA_FORMAT_YCrCb_420_SP		= 0xe,
+	RGA_FORMAT_YCrCb_420_P		= 0xf,
+
+	RGA_FORMAT_BPP1			= 0x10,
+	RGA_FORMAT_BPP2			= 0x11,
+	RGA_FORMAT_BPP4			= 0x12,
+	RGA_FORMAT_BPP8			= 0x13,
+
+	RGA_FORMAT_Y4			= 0x14,
+	RGA_FORMAT_YCbCr_400		= 0x15,
+
+	RGA_FORMAT_BGRX_8888		= 0x16,
+
+	RGA_FORMAT_YVYU_422		= 0x18,
+	RGA_FORMAT_YVYU_420		= 0x19,
+	RGA_FORMAT_VYUY_422		= 0x1a,
+	RGA_FORMAT_VYUY_420		= 0x1b,
+	RGA_FORMAT_YUYV_422		= 0x1c,
+	RGA_FORMAT_YUYV_420		= 0x1d,
+	RGA_FORMAT_UYVY_422		= 0x1e,
+	RGA_FORMAT_UYVY_420		= 0x1f,
+
+	RGA_FORMAT_YCbCr_420_SP_10B	= 0x20,
+	RGA_FORMAT_YCrCb_420_SP_10B	= 0x21,
+	RGA_FORMAT_YCbCr_422_SP_10B	= 0x22,
+	RGA_FORMAT_YCrCb_422_SP_10B	= 0x23,
+
+	RGA_FORMAT_BGR_565		= 0x24,
+	RGA_FORMAT_BGRA_5551		= 0x25,
+	RGA_FORMAT_BGRA_4444		= 0x26,
+
+	RGA_FORMAT_ARGB_8888		= 0x28,
+	RGA_FORMAT_XRGB_8888		= 0x29,
+	RGA_FORMAT_ARGB_5551		= 0x2a,
+	RGA_FORMAT_ARGB_4444		= 0x2b,
+	RGA_FORMAT_ABGR_8888		= 0x2c,
+	RGA_FORMAT_XBGR_8888		= 0x2d,
+	RGA_FORMAT_ABGR_5551		= 0x2e,
+	RGA_FORMAT_ABGR_4444		= 0x2f,
+
+	RGA_FORMAT_RGBA_2BPP		= 0x30,
+
+	RGA_FORMAT_UNKNOWN		= 0x100,
+};
+
+#define RGA_SCHED_PRIORITY_DEFAULT 0
+#define RGA_SCHED_PRIORITY_MAX 6
+
+#define RGA_VERSION_SIZE	16
+#define RGA_HW_SIZE		5
+
+struct rga_version_t {
+	uint32_t major;
+	uint32_t minor;
+	uint32_t revision;
+	uint8_t str[RGA_VERSION_SIZE];
+};
+
+struct rga_hw_versions_t {
+	struct rga_version_t version[RGA_HW_SIZE];
+	uint32_t size;
+};
+
+struct rga_memory_parm {
+	uint32_t width;
+	uint32_t height;
+	uint32_t format;
+
+	uint32_t size;
+};
+
+struct rga_external_buffer {
+	uint64_t memory;
+	uint32_t type;
+
+	uint32_t handle;
+	struct rga_memory_parm memory_parm;
+
+	uint8_t reserve[252];
+};
+
+struct rga_buffer_pool {
+	uint64_t buffers_ptr;
+	uint32_t size;
+};
+
+struct rga_color_fill_t {
+	int16_t gr_x_a;
+	int16_t gr_y_a;
+	int16_t gr_x_b;
+	int16_t gr_y_b;
+	int16_t gr_x_g;
+	int16_t gr_y_g;
+	int16_t gr_x_r;
+	int16_t gr_y_r;
+};
+
+/***************************************/
+/* porting from rga.h for msg convert */
+/***************************************/
+
+struct rga_fading_t {
+	uint8_t b;
+	uint8_t g;
+	uint8_t r;
+	uint8_t res;
+};
+
+struct rga_mmu_t {
+	uint8_t mmu_en;
+	uint64_t base_addr;
+	/*
+	 * [0] mmu enable [1] src_flush [2] dst_flush
+	 * [3] CMD_flush [4~5] page size
+	 */
+	uint32_t mmu_flag;
+};
+
+struct rga_rect_t {
+	uint16_t xmin;
+	/* width - 1 */
+	uint16_t xmax;
+	uint16_t ymin;
+	/* height - 1 */
+	uint16_t ymax;
+};
+
+struct rga_point_t {
+	uint16_t x;
+	uint16_t y;
+};
+
+struct rga_line_draw_t {
+	/* LineDraw_start_point	*/
+	struct rga_point_t start_point;
+	/* LineDraw_end_point */
+	struct rga_point_t end_point;
+	/* LineDraw_color */
+	uint32_t color;
+	/* (enum) LineDrawing mode sel */
+	uint32_t flag;
+	/* range 1~16 */
+	uint32_t line_width;
+};
+
+/* color space convert coefficient. */
+struct rga_csc_coe {
+	int16_t r_v;
+	int16_t g_y;
+	int16_t b_u;
+	int32_t off;
+};
+
+struct rga_full_csc {
+	uint8_t flag;
+	struct rga_csc_coe coe_y;
+	struct rga_csc_coe coe_u;
+	struct rga_csc_coe coe_v;
+};
+
+struct rga_mosaic_info {
+	uint8_t enable;
+	uint8_t mode;
+};
+
+/* MAX(min, (max - channel_value)) */
+struct rga_osd_invert_factor {
+	uint8_t alpha_max;
+	uint8_t alpha_min;
+	uint8_t yg_max;
+	uint8_t yg_min;
+	uint8_t crb_max;
+	uint8_t crb_min;
+};
+
+struct rga_color {
+	union {
+		struct {
+			uint8_t red;
+			uint8_t green;
+			uint8_t blue;
+			uint8_t alpha;
+		};
+		uint32_t value;
+	};
+};
+
+struct rga_osd_bpp2 {
+	uint8_t  ac_swap;		// ac swap flag
+					// 0: CA
+					// 1: AC
+	uint8_t  endian_swap;		// rgba2bpp endian swap
+					// 0: Big endian
+					// 1: Little endian
+	struct rga_color color0;
+	struct rga_color color1;
+};
+
+struct rga_osd_mode_ctrl {
+	uint8_t mode;			// OSD cal mode:
+					//   0b'1: statistics mode
+					//   1b'1: auto inversion overlap mode
+	uint8_t direction_mode;		// horizontal or vertical
+					//   0: horizontal
+					//   1: vertical
+	uint8_t width_mode;		// using @fix_width or LUT width
+					//   0: fix width
+					//   1: LUT width
+	uint16_t block_fix_width;	// OSD block fixed width
+					//   real width = (fix_width + 1) * 2
+	uint8_t block_num;		// OSD block num
+	uint16_t flags_index;		// auto invert flags index
+
+	/* invertion config */
+	uint8_t color_mode;		// selete color
+					//   0: src1 color
+					//   1: config data color
+	uint8_t invert_flags_mode;	// invert flag selete
+					//   0: use RAM flag
+					//   1: usr last result
+	uint8_t default_color_sel;	// default color mode
+					//   0: default is bright
+					//   1: default is dark
+	uint8_t invert_enable;		// invert channel enable
+					//   1 << 0: alpha enable
+					//   1 << 1: Y/G disable
+					//   1 << 3: C/RB disable
+	uint8_t invert_mode;		// invert cal mode
+					//   0: normal(max-data)
+					//   1: swap
+	uint8_t invert_thresh;		// if luma > thresh, osd_flag to be 1
+	uint8_t unfix_index;		// OSD width config index
+};
+
+struct rga_osd_info {
+	uint8_t  enable;
+
+	struct rga_osd_mode_ctrl mode_ctrl;
+	struct rga_osd_invert_factor cal_factor;
+	struct rga_osd_bpp2 bpp2_info;
+
+	union {
+		struct {
+			uint32_t last_flags0;
+			uint32_t last_flags1;
+		};
+		uint64_t last_flags;
+	};
+
+	union {
+		struct {
+			uint32_t cur_flags0;
+			uint32_t cur_flags1;
+		};
+		uint64_t cur_flags;
+	};
+};
+
+struct rga_pre_intr_info {
+	uint8_t enable;
+
+	uint8_t read_intr_en;
+	uint8_t write_intr_en;
+	uint8_t read_hold_en;
+	uint32_t read_threshold;
+	uint32_t write_start;
+	uint32_t write_step;
+};
+
+struct rga_img_info_t {
+	/* yrgb	mem addr */
+	uint64_t yrgb_addr;
+	/* cb/cr mem addr */
+	uint64_t uv_addr;
+	/* cr mem addr */
+	uint64_t v_addr;
+	/* definition by RK_FORMAT */
+	uint32_t format;
+
+	uint16_t act_w;
+	uint16_t act_h;
+	uint16_t x_offset;
+	uint16_t y_offset;
+
+	uint16_t vir_w;
+	uint16_t vir_h;
+
+	uint16_t endian_mode;
+	/* useless */
+	uint16_t alpha_swap;
+
+	/* used by RGA3 */
+	uint16_t rotate_mode;
+	uint16_t rd_mode;
+
+	uint16_t is_10b_compact;
+	uint16_t is_10b_endian;
+
+	uint16_t enable;
+};
+
+struct rga_req {
+	/* (enum) process mode sel */
+	uint8_t render_mode;
+
+	struct rga_img_info_t src;
+	struct rga_img_info_t dst;
+	struct rga_img_info_t pat;
+
+	/* rop4 mask addr */
+	uint64_t rop_mask_addr;
+	/* LUT addr */
+	uint64_t LUT_addr;
+
+	/* dst clip window default value is dst_vir */
+	/* value from [0, w-1] / [0, h-1]*/
+	struct rga_rect_t clip;
+
+	/* dst angle default value 0 16.16 scan from table */
+	int32_t sina;
+	/* dst angle default value 0 16.16 scan from table */
+	int32_t cosa;
+
+	/* alpha rop process flag		 */
+	/* ([0] = 1 alpha_rop_enable)	 */
+	/* ([1] = 1 rop enable)			 */
+	/* ([2] = 1 fading_enable)		 */
+	/* ([3] = 1 PD_enable)			 */
+	/* ([4] = 1 alpha cal_mode_sel)	 */
+	/* ([5] = 1 dither_enable)		 */
+	/* ([6] = 1 gradient fill mode sel) */
+	/* ([7] = 1 AA_enable)			 */
+	uint16_t alpha_rop_flag;
+
+	/* 0 nearst / 1 bilnear / 2 bicubic */
+	uint8_t scale_mode;
+
+	/* color key max */
+	uint32_t color_key_max;
+	/* color key min */
+	uint32_t color_key_min;
+
+	/* foreground color */
+	uint32_t fg_color;
+	/* background color */
+	uint32_t bg_color;
+
+	/* color fill use gradient */
+	struct rga_color_fill_t gr_color;
+
+	struct rga_line_draw_t line_draw_info;
+
+	struct rga_fading_t fading;
+
+	/* porter duff alpha mode sel */
+	uint8_t PD_mode;
+
+	/* global alpha value */
+	uint8_t alpha_global_value;
+
+	/* rop2/3/4 code scan from rop code table*/
+	uint16_t rop_code;
+
+	/* [2] 0 blur 1 sharp / [1:0] filter_type*/
+	uint8_t bsfilter_flag;
+
+	/* (enum) color palette 0/1bpp, 1/2bpp 2/4bpp 3/8bpp*/
+	uint8_t palette_mode;
+
+	/* (enum) BT.601 MPEG / BT.601 JPEG / BT.709 */
+	uint8_t yuv2rgb_mode;
+
+	/* 0/big endian 1/little endian*/
+	uint8_t endian_mode;
+
+	/* (enum) rotate mode */
+	/* 0x0,	 no rotate */
+	/* 0x1,	 rotate	 */
+	/* 0x2,	 x_mirror */
+	/* 0x3,	 y_mirror */
+	uint8_t rotate_mode;
+
+	/* 0 solid color / 1 pattern color */
+	uint8_t color_fill_mode;
+
+	/* mmu information */
+	struct rga_mmu_t mmu_info;
+
+	/* ([0~1] alpha mode)			*/
+	/* ([2~3] rop mode)			*/
+	/* ([4] zero mode en)		 */
+	/* ([5] dst alpha mode)	 */
+	/* ([6] alpha output mode sel) 0 src / 1 dst*/
+	uint8_t alpha_rop_mode;
+
+	uint8_t src_trans_mode;
+
+	uint8_t dither_mode;
+
+	/* full color space convert */
+	struct rga_full_csc full_csc;
+
+	int32_t in_fence_fd;
+	uint8_t core;
+	uint8_t priority;
+	int32_t out_fence_fd;
+
+	uint8_t handle_flag;
+
+	/* RGA2 1106 add */
+	struct rga_mosaic_info mosaic_info;
+
+	uint8_t uvhds_mode;
+	uint8_t uvvds_mode;
+
+	struct rga_osd_info osd_info;
+
+	struct rga_pre_intr_info pre_intr_info;
+
+	uint8_t reservr[59];
+};
+#endif /*_RGA_DRIVER_H_*/
diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index 93c426eeb3..325150f483 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -18,6 +18,10 @@
  * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
+#ifdef _POSIX_C_SOURCE
+#undef _POSIX_C_SOURCE
+#endif
+#define _POSIX_C_SOURCE 200809L /* for O_CLOEXEC */
 
 #include <drm_fourcc.h>
 #include <pthread.h>
@@ -26,6 +30,9 @@
 #include <time.h>
 #include <unistd.h>
 #include <sys/time.h>
+#include <sys/mman.h>
+#include <linux/dma-heap.h>
+#include <fcntl.h>
 
 #include "avcodec.h"
 #include "decode.h"
@@ -38,11 +45,8 @@
 #include "libavutil/hwcontext_drm.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/log.h"
+#include "rga.h"
 
-#if CONFIG_LIBRGA
-#include <rga/rga.h>
-#include <rga/RgaApi.h>
-#endif
 
 #ifndef DRM_FORMAT_NV12_10
 #define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '5')
@@ -50,11 +54,16 @@
 
 #define FPS_UPDATE_INTERVAL     120
 
+struct rkmpp_dma_buffer;
 typedef struct {
     MppCtx ctx;
     MppApi *mpi;
     MppBufferGroup frame_group;
 
+    int dma_fd;
+    struct rkmpp_dma_buffer *dma_cache;
+    int rga_fd;
+
     int8_t eos;
     int8_t draining;
 
@@ -115,17 +124,15 @@ static uint32_t rkmpp_get_avformat(MppFrameFormat mppformat)
     }
 }
 
-#if CONFIG_LIBRGA
 static uint32_t rkmpp_get_rgaformat(MppFrameFormat mppformat)
 {
     switch (mppformat) {
-    case MPP_FMT_YUV420SP:          return RK_FORMAT_YCbCr_420_SP;
-    case MPP_FMT_YUV420SP_10BIT:    return RK_FORMAT_YCbCr_420_SP_10B;
-    case MPP_FMT_YUV422SP:          return RK_FORMAT_YCbCr_422_SP;
-    default:                        return RK_FORMAT_UNKNOWN;
+    case MPP_FMT_YUV420SP:          return RGA_FORMAT_YCbCr_420_SP;
+    case MPP_FMT_YUV420SP_10BIT:    return RGA_FORMAT_YCbCr_420_SP_10B;
+    case MPP_FMT_YUV422SP:          return RGA_FORMAT_YCbCr_422_SP;
+    default:                        return RGA_FORMAT_UNKNOWN;
     }
 }
-#endif
 
 static int rkmpp_close_decoder(AVCodecContext *avctx)
 {
@@ -138,6 +145,8 @@ static int rkmpp_close_decoder(AVCodecContext *avctx)
     return 0;
 }
 
+static void rkmpp_buffer_free(struct rkmpp_dma_buffer *buffer);
+
 static void rkmpp_release_decoder(void *opaque, uint8_t *data)
 {
     RKMPPDecoder *decoder = (RKMPPDecoder *)data;
@@ -153,6 +162,20 @@ static void rkmpp_release_decoder(void *opaque, uint8_t *data)
         decoder->frame_group = NULL;
     }
 
+    rkmpp_buffer_free(decoder->dma_cache);
+    decoder->dma_cache = NULL;
+
+    if (decoder->dma_fd) {
+        close(decoder->dma_fd);
+        decoder->dma_fd = 0;
+    }
+
+    if (decoder->rga_fd) {
+        close(decoder->rga_fd);
+        decoder->rga_fd = 0;
+    }
+
+
     av_buffer_unref(&decoder->frames_ref);
     av_buffer_unref(&decoder->device_ref);
 
@@ -250,13 +273,27 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
         goto fail;
     }
 
-    ret = mpp_buffer_group_get_internal(&decoder->frame_group, MPP_BUFFER_TYPE_ION);
+    ret = mpp_buffer_group_get_internal(&decoder->frame_group,
+                                        MPP_BUFFER_TYPE_DMA_HEAP);
+
     if (ret) {
        av_log(avctx, AV_LOG_ERROR, "Failed to get buffer group (code = %d)\n", ret);
        ret = AVERROR_UNKNOWN;
        goto fail;
     }
 
+    decoder->dma_fd = open("/dev/dma_heap/system-dma32", O_RDWR);
+    if (decoder->dma_fd < 0) {
+       av_log(avctx, AV_LOG_ERROR, "Failed to open system-dma32 heap\n");
+       ret = AVERROR_UNKNOWN;
+       goto fail;
+    }
+
+    decoder->rga_fd = open("/dev/rga", O_RDWR);
+    if (decoder->dma_fd < 0) {
+       av_log(avctx, AV_LOG_WARNING, "Failed to open RGA\n");
+    }
+
     ret = decoder->mpi->control(decoder->ctx, MPP_DEC_SET_EXT_BUF_GROUP, decoder->frame_group);
     if (ret) {
         av_log(avctx, AV_LOG_ERROR, "Failed to assign buffer group (code = %d)\n", ret);
@@ -307,13 +344,14 @@ static void rkmpp_release_frame(void *opaque, uint8_t *data)
 static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame,
                                MppFrame mppframe, MppBuffer buffer)
 {
+    RKMPPDecodeContext *rk_context = avctx->priv_data;
+    RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+
     char *src = mpp_buffer_get_ptr(buffer);
     char *dst_y = frame->data[0];
     char *dst_u = frame->data[1];
     char *dst_v = frame->data[2];
-#if CONFIG_LIBRGA
-    RgaSURF_FORMAT format = rkmpp_get_rgaformat(mpp_frame_get_fmt(mppframe));
-#endif
+    enum rga_surf_format format = rkmpp_get_rgaformat(mpp_frame_get_fmt(mppframe));
     int width = mpp_frame_get_width(mppframe);
     int height = mpp_frame_get_height(mppframe);
     int hstride = mpp_frame_get_hor_stride(mppframe);
@@ -321,29 +359,41 @@ static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame,
     int y_pitch = frame->linesize[0];
     int u_pitch = frame->linesize[1];
     int v_pitch = frame->linesize[2];
-    int i, j;
+    int i, j, ret;
 
-#if CONFIG_LIBRGA
-    rga_info_t src_info = {0};
-    rga_info_t dst_info = {0};
     int dst_height = (dst_u - dst_y) / y_pitch;
 
-    static int rga_supported = 1;
-    static int rga_inited = 0;
+    struct rga_req req = {
+        .src = {
+            .yrgb_addr = mpp_buffer_get_fd(buffer),
+            .v_addr = hstride * vstride,
+            .format = format,
+            .act_w = width,
+            .act_h = height,
+            .vir_w = hstride,
+            .vir_h = vstride,
+            .rd_mode = RGA_RASTER_MODE,
+        },
+        .dst = {
+            .uv_addr = (uintptr_t) dst_y,
+            .v_addr = (uintptr_t) dst_u,
+            .format = RGA_FORMAT_YCbCr_420_P,
+            .act_w = width,
+            .act_h = height,
+            .vir_w = y_pitch,
+            .vir_h = dst_height,
+            .rd_mode = RGA_RASTER_MODE,
+        },
+        .mmu_info = {
+            .mmu_en = 1,
+            .mmu_flag = 0x80000521,
+        },
+    };
 
-    if (!rga_supported)
+    if (decoder->rga_fd < 0)
         goto bail;
 
-    if (!rga_inited) {
-        if (c_RkRgaInit() < 0) {
-            rga_supported = 0;
-            av_log(avctx, AV_LOG_WARNING, "RGA not available\n");
-            goto bail;
-        }
-        rga_inited = 1;
-    }
-
-    if (format == RK_FORMAT_UNKNOWN)
+    if (format == RGA_FORMAT_UNKNOWN)
         goto bail;
 
     if (u_pitch != y_pitch / 2 || v_pitch != y_pitch / 2 ||
@@ -351,23 +401,13 @@ static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame,
         dst_v != dst_u + u_pitch * dst_height / 2)
         goto bail;
 
-    src_info.fd = mpp_buffer_get_fd(buffer);
-    src_info.mmuFlag = 1;
-    rga_set_rect(&src_info.rect, 0, 0, width, height, hstride, vstride,
-                 format);
-
-    dst_info.virAddr = dst_y;
-    dst_info.mmuFlag = 1;
-    rga_set_rect(&dst_info.rect, 0, 0, frame->width, frame->height,
-                 y_pitch, dst_height, RK_FORMAT_YCbCr_420_P);
-
-    if (c_RkRgaBlit(&src_info, &dst_info, NULL) < 0)
+    ret = ioctl(decoder->rga_fd, RGA_BLIT_SYNC, &req);
+    if (ret < 0)
         goto bail;
 
     return 0;
 
 bail:
-#endif
     if (mpp_frame_get_fmt(mppframe) != MPP_FMT_YUV420SP) {
         av_log(avctx, AV_LOG_WARNING, "Unable to convert\n");
         return -1;
@@ -423,6 +463,150 @@ static void rkmpp_update_fps(AVCodecContext *avctx)
            fps, decoder->frames);
 }
 
+struct rkmpp_dma_buffer {
+    int fd;
+    void *cpu;
+    size_t size;
+    struct rkmpp_dma_buffer **cache;
+};
+
+static void rkmpp_buffer_free(struct rkmpp_dma_buffer *buffer)
+{
+    if (!buffer)
+        return;
+
+    munmap(buffer->cpu, buffer->size);
+    close(buffer->fd);
+    av_free(buffer);
+}
+
+static void rkmpp_buffer_cache(void *opaque, uint8_t *data)
+{
+    struct rkmpp_dma_buffer *buffer = opaque;
+
+    if (!buffer)
+        return;
+
+    if (*buffer->cache)
+        rkmpp_buffer_free(buffer);
+    else
+        *buffer->cache = buffer;
+}
+
+static struct rkmpp_dma_buffer *rkmpp_buffer_alloc(RKMPPDecoder *decoder, size_t size)
+{
+    struct rkmpp_dma_buffer *buffer;
+    int ret;
+
+    struct dma_heap_allocation_data alloc = {
+        .len = size,
+        .fd_flags = O_CLOEXEC | O_RDWR,
+    };
+
+    if (decoder->dma_cache) {
+        struct rkmpp_dma_buffer *cached = decoder->dma_cache;
+        decoder->dma_cache = NULL;
+
+        if (cached->size == size) {
+            return cached;
+        }
+
+        rkmpp_buffer_free(cached);
+    }
+
+    ret = ioctl(decoder->dma_fd, DMA_HEAP_IOCTL_ALLOC, &alloc);
+    if (ret == -1)
+        return NULL;
+
+    buffer = av_mallocz(sizeof(*buffer));
+    buffer->fd = alloc.fd;
+    buffer->size = alloc.len;
+    buffer->cpu = mmap(NULL, buffer->size, PROT_READ | PROT_WRITE,
+                       MAP_SHARED, buffer->fd, 0);
+    buffer->cache = &decoder->dma_cache;
+
+    return buffer;
+}
+
+static int rkmpp_get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flags)
+{
+    RKMPPDecodeContext *rk_context = avctx->priv_data;
+    RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+
+    int ret;
+
+    int linesize[4];
+    int stride_align[AV_NUM_DATA_POINTERS];
+    int w = pic->width;
+    int h = pic->height;
+    int unaligned;
+    ptrdiff_t linesize1[4];
+    size_t size[4];
+
+    struct rkmpp_dma_buffer *buffer;
+
+    int total;
+
+    avcodec_align_dimensions2(avctx, &w, &h, stride_align);
+
+    do {
+        // NOTE: do not align linesizes individually, this breaks e.g. assumptions
+        // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2
+        ret = av_image_fill_linesizes(linesize, avctx->pix_fmt, w);
+        if (ret < 0)
+            goto fail;
+        // increase alignment of w for next try (rhs gives the lowest bit set in w)
+        w += w & ~(w - 1);
+
+        unaligned = 0;
+        for (int i = 0; i < 4; i++)
+            unaligned |= linesize[i] % stride_align[i];
+    } while (unaligned);
+
+    for (int i = 0; i < 4; i++)
+        linesize1[i] = linesize[i];
+    ret = av_image_fill_plane_sizes(size, avctx->pix_fmt, h, linesize1);
+    if (ret < 0)
+        goto fail;
+
+    size[0] += size[1] + size[2] + size[3];
+    size[0] += 16 + STRIDE_ALIGN - 1;
+
+    buffer = rkmpp_buffer_alloc(decoder, size[0]);
+    if (!buffer)
+        goto fail;
+
+    av_log(avctx, AV_LOG_DEBUG, "Allocated buffer of size %zi -> %p (CPU %p)\n", size[0], buffer, buffer->cpu);
+
+    memset(pic->data, 0, sizeof(pic->data));
+    pic->extended_data = pic->data;
+
+    pic->linesize[0] = linesize[0];
+    pic->buf[0] = av_buffer_create(buffer->cpu, size[0],
+                                   rkmpp_buffer_cache, buffer, 0);
+    pic->data[0] = pic->buf[0]->data;
+
+    for (int i = 1; i < 4; i++)
+        pic->linesize[i] = linesize[i];
+
+    total = av_image_fill_pointers(pic->data, pic->format, pic->height,
+                                  pic->buf[0]->data, pic->linesize);
+    if (total < 0 || total > pic->buf[0]->size)
+        goto fail;
+
+    for (int i = 4; i < AV_NUM_DATA_POINTERS; i++) {
+        pic->data[i] = NULL;
+        pic->linesize[i] = 0;
+    }
+
+    return 0;
+
+fail:
+    av_frame_unref(pic);
+    return AVERROR(ENOMEM);
+}
+
+
 static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
@@ -528,6 +712,8 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
     rkmpp_update_fps(avctx);
 
     if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) {
+    	avctx->get_buffer2 = rkmpp_get_buffer2;
+
         ret = ff_get_buffer(avctx, frame, 0);
         if (ret < 0)
             goto out;
-- 
2.40.0


From 3da5435d3ae03dc59175f966ef904645537aa8ae Mon Sep 17 00:00:00 2001
From: boogie <boogiepop@gmx.com>
Date: Tue, 17 Jan 2023 01:02:19 +0100
Subject: [PATCH 16/18] ugliest hack: vp8&9 color space workaround

---
 libavcodec/rkmppdec.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index 325150f483..ad9208f0e6 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -734,6 +734,21 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
     frame->color_trc        = mpp_frame_get_color_trc(mppframe);
     frame->colorspace       = mpp_frame_get_colorspace(mppframe);
 
+    /* ugliest hack in the world: firefox does not probe with avformat, so it does not
+     * have any idea about the frame format, instead tries to guess with decoder profile
+     * matches. Since this decoder does not provide any profile, it just sets color pro-
+     * file to 0 which RGB. This causes funny coloring on video decode.
+     * I set this manually to most popular BT709 colorspace for VP8&9. This worksaround
+     * youtube problems, but does not work always. At least there is no need to run this
+     * on each frame... But yeah it is too late and i dont care.
+    */
+    if ((avctx->codec_id == AV_CODEC_ID_VP8 || avctx->codec_id == AV_CODEC_ID_VP9 ) \
+    		&& avctx->profile == FF_PROFILE_UNKNOWN && !frame->colorspace){
+    	frame->color_primaries = AVCOL_PRI_BT709;
+    	frame->color_trc = AVCOL_TRC_BT709;
+    	frame->colorspace = AVCOL_SPC_BT709;
+    }
+
     mode = mpp_frame_get_mode(mppframe);
     frame->interlaced_frame = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED);
     frame->top_field_first  = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST);
-- 
2.40.0


From 07f976d610833f6198ab12af514e945108d23708 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Tue, 17 Jan 2023 18:31:57 +0800
Subject: [PATCH 17/18] rkmppdec: AV1 support

---
 configure              |  1 +
 libavcodec/Makefile    |  2 ++
 libavcodec/allcodecs.c |  1 +
 libavcodec/rkmppdec.c  | 14 ++------------
 4 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/configure b/configure
index 6e72375e09..6926a58f95 100755
--- a/configure
+++ b/configure
@@ -3072,6 +3072,7 @@ nvenc_encoder_deps="nvenc"
 aac_mf_encoder_deps="mediafoundation"
 ac3_mf_encoder_deps="mediafoundation"
 av1_cuvid_decoder_deps="cuvid CUVIDAV1PICPARAMS"
+av1_rkmpp_decoder_deps="rkmpp"
 h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m"
 h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m"
 h263_rkmpp_decoder_deps="rkmpp"
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 345b6a5816..004a00c761 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -60,6 +60,8 @@ OBJS = ac3_parser.o                                                     \
        xiph.o                                                           \
 
 # subsystems
+OBJS-$(CONFIG_AV1_RKMPP_DECODER)       += rkmppdec.o
+
 OBJS-$(CONFIG_AANDCTTABLES)            += aandcttab.o
 OBJS-$(CONFIG_AC3DSP)                  += ac3dsp.o ac3.o ac3tab.o
 OBJS-$(CONFIG_ADTS_HEADER)             += adts_header.o mpeg4audio.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 409e7f33e4..dc9104fb75 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -29,6 +29,7 @@
 #include "avcodec.h"
 #include "version.h"
 
+extern AVCodec ff_av1_rkmpp_decoder;
 extern AVCodec ff_a64multi_encoder;
 extern AVCodec ff_a64multi5_encoder;
 extern AVCodec ff_aasc_decoder;
diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index ad9208f0e6..452c89a590 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -95,6 +95,7 @@ static MppCodingType rkmpp_get_codingtype(AVCodecContext *avctx)
     case AV_CODEC_ID_H263:          return MPP_VIDEO_CodingH263;
     case AV_CODEC_ID_H264:          return MPP_VIDEO_CodingAVC;
     case AV_CODEC_ID_HEVC:          return MPP_VIDEO_CodingHEVC;
+    case AV_CODEC_ID_AV1:           return MPP_VIDEO_CodingAV1;
     case AV_CODEC_ID_VP8:           return MPP_VIDEO_CodingVP8;
     case AV_CODEC_ID_VP9:           return MPP_VIDEO_CodingVP9;
     case AV_CODEC_ID_MPEG1VIDEO:    /* fallthrough */
@@ -186,20 +187,8 @@ static int rkmpp_prepare_decoder(AVCodecContext *avctx)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
     RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
-    MppPacket packet;
     int ret;
 
-    // send extra data
-    if (avctx->extradata_size) {
-        ret = mpp_packet_init(&packet, avctx->extradata, avctx->extradata_size);
-        if (ret < 0)
-            return AVERROR_UNKNOWN;
-        ret = decoder->mpi->decode_put_packet(decoder->ctx, packet);
-        mpp_packet_deinit(&packet);
-        if (ret < 0)
-            return AVERROR_UNKNOWN;
-    }
-
     if (getenv("FFMPEG_RKMPP_SYNC")) {
         // wait for decode result after feeding any packets
         decoder->sync = 1;
@@ -1000,6 +989,7 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
 RKMPP_DEC(h263,  AV_CODEC_ID_H263,          NULL)
 RKMPP_DEC(h264,  AV_CODEC_ID_H264,          "h264_mp4toannexb")
 RKMPP_DEC(hevc,  AV_CODEC_ID_HEVC,          "hevc_mp4toannexb")
+RKMPP_DEC(av1,   AV_CODEC_ID_AV1,           NULL)
 RKMPP_DEC(vp8,   AV_CODEC_ID_VP8,           NULL)
 RKMPP_DEC(vp9,   AV_CODEC_ID_VP9,           NULL)
 RKMPP_DEC(mpeg1, AV_CODEC_ID_MPEG1VIDEO,    NULL)
-- 
2.40.0


From f37ea966915150e661b805208c855d2fc14e1a18 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Mon, 27 Mar 2023 17:44:09 +0800
Subject: [PATCH 18/18] rkmppdec: Ignore special MPP format masks

We should use the basic format in format conversion.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 libavcodec/rkmppdec.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index 452c89a590..735478da9b 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -107,7 +107,7 @@ static MppCodingType rkmpp_get_codingtype(AVCodecContext *avctx)
 
 static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
 {
-    switch (mppformat) {
+    switch (mppformat & MPP_FRAME_FMT_MASK) {
     case MPP_FMT_YUV420SP:          return DRM_FORMAT_NV12;
     case MPP_FMT_YUV420SP_10BIT:    return DRM_FORMAT_NV12_10;
     case MPP_FMT_YUV422SP:          return DRM_FORMAT_NV16;
@@ -117,7 +117,7 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
 
 static uint32_t rkmpp_get_avformat(MppFrameFormat mppformat)
 {
-    switch (mppformat) {
+    switch (mppformat & MPP_FRAME_FMT_MASK) {
     case MPP_FMT_YUV420SP:          return AV_PIX_FMT_NV12;
     case MPP_FMT_YUV420SP_10BIT:    return AV_PIX_FMT_NONE;
     case MPP_FMT_YUV422SP:          return AV_PIX_FMT_NV16;
@@ -127,7 +127,7 @@ static uint32_t rkmpp_get_avformat(MppFrameFormat mppformat)
 
 static uint32_t rkmpp_get_rgaformat(MppFrameFormat mppformat)
 {
-    switch (mppformat) {
+    switch (mppformat & MPP_FRAME_FMT_MASK) {
     case MPP_FMT_YUV420SP:          return RGA_FORMAT_YCbCr_420_SP;
     case MPP_FMT_YUV420SP_10BIT:    return RGA_FORMAT_YCbCr_420_SP_10B;
     case MPP_FMT_YUV422SP:          return RGA_FORMAT_YCbCr_422_SP;
-- 
2.40.0