1 /*
2    mkvmerge -- utility for splicing together matroska files
3    from component media subtypes
4 
5    Distributed under the GPL v2
6    see the file COPYING for details
7    or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
8 
9    MPEG4 part 10 video output module
10 
11    Written by Moritz Bunkus <moritz@bunkus.org>.
12 */
13 
14 #include "common/common_pch.h"
15 
16 #include <cmath>
17 
18 #include "common/avc/es_parser.h"
19 #include "common/codec.h"
20 #include "common/endian.h"
21 #include "common/hacks.h"
22 #include "common/list_utils.h"
23 #include "common/mpeg.h"
24 #include "common/strings/formatting.h"
25 #include "merge/output_control.h"
26 #include "output/p_avc.h"
27 
28 avc_video_packetizer_c::
avc_video_packetizer_c(generic_reader_c * p_reader,track_info_c & p_ti,int64_t default_duration,int width,int height)29 avc_video_packetizer_c(generic_reader_c *p_reader,
30                        track_info_c &p_ti,
31                        int64_t default_duration,
32                        int width,
33                        int height)
34   : generic_video_packetizer_c{p_reader, p_ti, MKV_V_MPEG4_AVC, default_duration, width, height}
35   , m_debug_fix_bistream_timing_info{"fix_bitstream_timing_info"}
36 {
37   m_relaxed_timestamp_checking = true;
38 
39   if (5 <= m_ti.m_private_data->get_size())
40     m_nalu_size_len = (m_ti.m_private_data->get_buffer()[4] & 0x03) + 1;
41 
42   set_codec_private(m_ti.m_private_data);
43 }
44 
45 void
set_headers()46 avc_video_packetizer_c::set_headers() {
47   if (m_ti.m_private_data && m_ti.m_private_data->get_size())
48     extract_aspect_ratio();
49 
50   int64_t divisor = 2;
51 
52   if (m_default_duration_forced) {
53     if (m_htrack_default_duration_indicates_fields) {
54       set_track_default_duration(m_htrack_default_duration / 2, true);
55       divisor = 1;
56     }
57 
58     m_track_default_duration = m_htrack_default_duration;
59   }
60 
61   if ((-1 == m_track_default_duration) && m_timestamp_factory)
62     m_track_default_duration = m_timestamp_factory->get_default_duration(-1);
63 
64   if ((-1 == m_track_default_duration) && (0 < m_default_duration))
65     m_track_default_duration = m_default_duration;
66 
67   if (-1 != m_track_default_duration)
68     m_track_default_duration /= divisor;
69 
70   mxdebug_if(m_debug_fix_bistream_timing_info,
71              fmt::format("fix_bitstream_timing_info [AVCC]: factory default_duration {0} default_duration_forced? {1} htrack_default_duration {2} default_duration {3} m_track_default_duration {4}\n",
72                          m_timestamp_factory ? m_timestamp_factory->get_default_duration(-1) : -2,
73                          m_default_duration_forced, m_htrack_default_duration,
74                          m_default_duration, m_track_default_duration));
75 
76   if (   m_ti.m_private_data
77       && m_ti.m_private_data->get_size()
78       && m_ti.m_fix_bitstream_frame_rate
79       && (-1 != m_track_default_duration))
80     set_codec_private(mtx::avc::fix_sps_fps(m_ti.m_private_data, m_track_default_duration));
81 
82   generic_video_packetizer_c::set_headers();
83 }
84 
85 void
extract_aspect_ratio()86 avc_video_packetizer_c::extract_aspect_ratio() {
87   auto result = mtx::avc::extract_par(m_ti.m_private_data);
88 
89   set_codec_private(result.new_avcc);
90 
91   if (!result.is_valid() || display_dimensions_or_aspect_ratio_set())
92     return;
93 
94   auto par = mtx::rational(result.numerator, result.denominator);
95 
96   set_video_display_dimensions(1 <= par ? mtx::to_int_rounded(m_width * par) : m_width,
97                                1 <= par ? m_height                           : mtx::to_int_rounded(m_height / par),
98                                generic_packetizer_c::ddu_pixels,
99                                OPTION_SOURCE_BITSTREAM);
100 
101   mxinfo_tid(m_ti.m_fname, m_ti.m_id,
102              fmt::format(Y("Extracted the aspect ratio information from the MPEG-4 layer 10 (AVC) video data and set the display dimensions to {0}/{1}.\n"),
103                          m_ti.m_display_width, m_ti.m_display_height));
104 }
105 
106 void
process_impl(packet_cptr const & packet)107 avc_video_packetizer_c::process_impl(packet_cptr const &packet) {
108   if (VFT_PFRAMEAUTOMATIC == packet->bref) {
109     packet->fref = -1;
110     packet->bref = m_ref_timestamp;
111   }
112 
113   m_ref_timestamp = packet->timestamp;
114 
115   process_nalus(*packet->data);
116 
117   add_packet(packet);
118 }
119 
120 connection_result_e
can_connect_to(generic_packetizer_c * src,std::string & error_message)121 avc_video_packetizer_c::can_connect_to(generic_packetizer_c *src,
122                                        std::string &error_message) {
123   avc_video_packetizer_c *vsrc = dynamic_cast<avc_video_packetizer_c *>(src);
124   if (!vsrc)
125     return CAN_CONNECT_NO_FORMAT;
126 
127   if (m_ti.m_private_data && vsrc->m_ti.m_private_data && memcmp(m_ti.m_private_data->get_buffer(), vsrc->m_ti.m_private_data->get_buffer(), m_ti.m_private_data->get_size())) {
128     error_message = fmt::format(Y("The codec's private data does not match. Both have the same length ({0}) but different content."), m_ti.m_private_data->get_size());
129     return CAN_CONNECT_MAYBE_CODECPRIVATE;
130   }
131 
132   return CAN_CONNECT_YES;
133 }
134 
135 void
process_nalus(memory_c & data) const136 avc_video_packetizer_c::process_nalus(memory_c &data)
137   const {
138   auto ptr        = data.get_buffer();
139   auto total_size = data.get_size();
140   auto idx        = 0u;
141 
142   while ((idx + m_nalu_size_len) < total_size) {
143     auto nalu_size = get_uint_be(&ptr[idx], m_nalu_size_len) + m_nalu_size_len;
144 
145     if ((idx + nalu_size) > total_size)
146       break;
147 
148     if (static_cast<int>(nalu_size) < m_nalu_size_len)
149       break;
150 
151     auto const nalu_type = ptr[idx + m_nalu_size_len] & 0x1f;
152 
153     if (   (static_cast<int>(nalu_size) == m_nalu_size_len) // empty NALU?
154         || mtx::included_in(nalu_type, mtx::avc::NALU_TYPE_FILLER_DATA, mtx::avc::NALU_TYPE_ACCESS_UNIT)) {
155       memory_c::splice(data, idx, nalu_size);
156       total_size -= nalu_size;
157       ptr         = data.get_buffer();
158       continue;
159     }
160 
161     if (   (nalu_type == mtx::avc::NALU_TYPE_SEQ_PARAM)
162         && m_ti.m_fix_bitstream_frame_rate
163         && (-1 != m_track_default_duration)) {
164       mxdebug_if(m_debug_fix_bistream_timing_info, fmt::format("fix_bitstream_timing_info [NALU]: m_track_default_duration {0}\n", m_track_default_duration));
165 
166       mtx::avc::sps_info_t sps_info;
167       auto parsed_nalu = mtx::avc::parse_sps(mtx::mpeg::nalu_to_rbsp(memory_c::clone(&ptr[idx + m_nalu_size_len], nalu_size - m_nalu_size_len)), sps_info, true, true, m_track_default_duration);
168 
169       if (parsed_nalu) {
170         parsed_nalu = mtx::mpeg::rbsp_to_nalu(parsed_nalu);
171 
172         memory_c::splice(data, idx + m_nalu_size_len, nalu_size - m_nalu_size_len, *parsed_nalu);
173 
174         total_size = data.get_size();
175         ptr        = data.get_buffer();
176 
177         put_uint_be(&ptr[idx], parsed_nalu->get_size(), m_nalu_size_len);
178 
179         idx += parsed_nalu->get_size() + m_nalu_size_len;
180         continue;
181       }
182     }
183 
184     idx += nalu_size;
185   }
186 
187   // empty NALU at the end?
188   if (total_size == (idx + m_nalu_size_len))
189     data.set_size(idx);
190 }
191