1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h"
7 #include "base/logging.h"
8 #include "media/ffmpeg/ffmpeg_common.h"
12 FFmpegH264ToAnnexBBitstreamConverter::FFmpegH264ToAnnexBBitstreamConverter(
13 AVCodecContext* stream_context)
14 : configuration_processed_(false),
15 stream_context_(stream_context) {
16 CHECK(stream_context_);
19 FFmpegH264ToAnnexBBitstreamConverter::~FFmpegH264ToAnnexBBitstreamConverter() {}
21 bool FFmpegH264ToAnnexBBitstreamConverter::ConvertPacket(AVPacket* packet) {
22 uint32 output_packet_size = 0;
23 uint32 configuration_size = 0;
29 // Calculate the needed output buffer size.
30 if (!configuration_processed_) {
31 // FFmpeg's AVCodecContext's extradata field contains the Decoder
32 // Specific Information from MP4 headers that contain the H.264 SPS and
33 // PPS members. See ISO/IEC 14496-15 Chapter 5.2.4
34 // AVCDecoderConfigurationRecord for exact specification.
35 // Extradata must be at least 7 bytes long.
36 if (stream_context_->extradata == NULL ||
37 stream_context_->extradata_size <= 7) {
38 return false; // Can't go on with conversion without configuration.
40 configuration_size += converter_.ParseConfigurationAndCalculateSize(
41 stream_context_->extradata,
42 stream_context_->extradata_size);
43 if (configuration_size == 0) {
44 return false; // Not possible to parse the configuration.
47 uint32 output_nal_size =
48 converter_.CalculateNeededOutputBufferSize(packet->data, packet->size);
49 if (output_nal_size == 0) {
50 return false; // Invalid input packet.
52 output_packet_size = configuration_size + output_nal_size;
54 // Allocate new packet for the output.
56 if (av_new_packet(&dest_packet, output_packet_size) != 0) {
57 return false; // Memory allocation failure.
59 // This is a bit tricky: since the interface does not allow us to replace
60 // the pointer of the old packet with a new one, we will initially copy the
61 // metadata from old packet to new bigger packet.
62 dest_packet.pts = packet->pts;
63 dest_packet.dts = packet->dts;
64 dest_packet.pos = packet->pos;
65 dest_packet.duration = packet->duration;
66 dest_packet.convergence_duration = packet->convergence_duration;
67 dest_packet.flags = packet->flags;
68 dest_packet.stream_index = packet->stream_index;
70 // Process the configuration if not done earlier.
71 if (!configuration_processed_) {
72 if (!converter_.ConvertAVCDecoderConfigToByteStream(
73 stream_context_->extradata, stream_context_->extradata_size,
74 dest_packet.data, &configuration_size)) {
75 return false; // Failed to convert the buffer.
77 configuration_processed_ = true;
80 // Proceed with the conversion of the actual in-band NAL units, leave room
81 // for configuration in the beginning.
82 io_size = dest_packet.size - configuration_size;
83 if (!converter_.ConvertNalUnitStreamToByteStream(
84 packet->data, packet->size,
85 dest_packet.data + configuration_size, &io_size)) {
89 // At the end we must destroy the old packet.
90 av_free_packet(packet);
91 *packet = dest_packet; // Finally, replace the values in the input packet.