- add sources.
[platform/framework/web/crosswalk.git] / src / media / filters / ffmpeg_h264_to_annex_b_bitstream_converter.cc
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.
4
5 #include "media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h"
6
7 #include "base/logging.h"
8 #include "media/ffmpeg/ffmpeg_common.h"
9
10 namespace media {
11
12 FFmpegH264ToAnnexBBitstreamConverter::FFmpegH264ToAnnexBBitstreamConverter(
13     AVCodecContext* stream_context)
14     : configuration_processed_(false),
15       stream_context_(stream_context) {
16   CHECK(stream_context_);
17 }
18
19 FFmpegH264ToAnnexBBitstreamConverter::~FFmpegH264ToAnnexBBitstreamConverter() {}
20
21 bool FFmpegH264ToAnnexBBitstreamConverter::ConvertPacket(AVPacket* packet) {
22   uint32 output_packet_size = 0;
23   uint32 configuration_size = 0;
24   uint32 io_size = 0;
25   if (packet == NULL) {
26     return false;
27   }
28
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.
39     }
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.
45     }
46   }
47   uint32 output_nal_size =
48       converter_.CalculateNeededOutputBufferSize(packet->data, packet->size);
49   if (output_nal_size == 0) {
50     return false;  // Invalid input packet.
51   }
52   output_packet_size = configuration_size + output_nal_size;
53
54   // Allocate new packet for the output.
55   AVPacket dest_packet;
56   if (av_new_packet(&dest_packet, output_packet_size) != 0) {
57     return false;  // Memory allocation failure.
58   }
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;
69
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.
76     }
77     configuration_processed_ = true;
78   }
79
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)) {
86     return false;
87   }
88
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.
92
93   return true;
94 }
95
96 }  // namespace media
97