Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / media / filters / ffmpeg_h265_to_annex_b_bitstream_converter.cc
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.h"
6
7 #include <stdint.h>
8
9 #include "base/logging.h"
10 #include "media/base/decrypt_config.h"
11 #include "media/ffmpeg/ffmpeg_common.h"
12 #include "media/formats/mp4/avc.h"
13 #include "media/formats/mp4/box_definitions.h"
14 #include "media/formats/mp4/hevc.h"
15
16 namespace media {
17
18 FFmpegH265ToAnnexBBitstreamConverter::FFmpegH265ToAnnexBBitstreamConverter(
19     AVCodecParameters* stream_codec_parameters)
20     : stream_codec_parameters_(stream_codec_parameters) {
21   CHECK(stream_codec_parameters_);
22 }
23
24 FFmpegH265ToAnnexBBitstreamConverter::~FFmpegH265ToAnnexBBitstreamConverter() {}
25
26 bool FFmpegH265ToAnnexBBitstreamConverter::ConvertPacket(AVPacket* packet) {
27   DVLOG(3) << __func__;
28   if (packet == NULL || !packet->data)
29     return false;
30
31   // Calculate the needed output buffer size.
32   if (!hevc_config_) {
33     if (!stream_codec_parameters_->extradata ||
34         stream_codec_parameters_->extradata_size <= 0) {
35       DVLOG(1) << "HEVCDecoderConfiguration not found, no extra codec data";
36       return false;
37     }
38
39     hevc_config_.reset(new mp4::HEVCDecoderConfigurationRecord());
40
41     if (!hevc_config_->Parse(stream_codec_parameters_->extradata,
42                              stream_codec_parameters_->extradata_size)) {
43       DVLOG(1) << "Parsing HEVCDecoderConfiguration failed";
44       return false;
45     }
46   }
47
48   std::vector<uint8_t> input_frame;
49   std::vector<SubsampleEntry> subsamples;
50   // TODO(servolk): Performance could be improved here, by reducing unnecessary
51   // data copying, but first annex b conversion code needs to be refactored to
52   // allow that (see crbug.com/455379).
53   input_frame.insert(input_frame.end(),
54                      packet->data, packet->data + packet->size);
55   size_t nalu_size_len = hevc_config_->lengthSizeMinusOne + 1;
56   if (!mp4::AVC::ConvertFrameToAnnexB(nalu_size_len, &input_frame,
57                                       &subsamples)) {
58     DVLOG(1) << "AnnexB conversion failed";
59     return false;
60   }
61
62   if (packet->flags & AV_PKT_FLAG_KEY) {
63     RCHECK(mp4::HEVC::InsertParamSetsAnnexB(*hevc_config_.get(),
64                                             &input_frame, &subsamples));
65     DVLOG(4) << "Inserted HEVC decoder params";
66   }
67
68   uint32_t output_packet_size = input_frame.size();
69
70   if (output_packet_size == 0)
71     return false;  // Invalid input packet.
72
73   // Allocate new packet for the output.
74   AVPacket dest_packet;
75   if (av_new_packet(&dest_packet, output_packet_size) != 0)
76     return false;  // Memory allocation failure.
77
78   // This is a bit tricky: since the interface does not allow us to replace
79   // the pointer of the old packet with a new one, we will initially copy the
80   // metadata from old packet to new bigger packet.
81   av_packet_copy_props(&dest_packet, packet);
82
83   // Proceed with the conversion of the actual in-band NAL units, leave room
84   // for configuration in the beginning.
85   memcpy(dest_packet.data, &input_frame[0], input_frame.size());
86
87   // At the end we must destroy the old packet.
88   av_packet_unref(packet);
89
90   // Finally, replace the values in the input packet.
91   memcpy(packet, &dest_packet, sizeof(*packet));
92   return true;
93 }
94
95 }  // namespace media