Bug 1035059 - Add input padding for libav; r=edwin
authorAnthony Jones <ajones@mozilla.com>
Fri, 11 Jul 2014 18:43:59 +1200
changeset 193540 a9ad61be640668d2a610c861a5184e6cf658e15c
parent 193539 d95cd8921f2ce54eb7e989b9502d1d8e4ccdd0bc
child 193541 01291e659c2bba7eb7e8bf2f6b5bc299f06d5aca
push id27123
push userryanvm@gmail.com
push dateFri, 11 Jul 2014 20:35:05 +0000
treeherdermozilla-central@84bd8d9f4256 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersedwin
bugs1035059
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1035059 - Add input padding for libav; r=edwin
content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp
content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp
content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp
media/libstagefright/binding/DecoderData.cpp
media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
--- a/content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp
+++ b/content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp
@@ -66,16 +66,17 @@ void
 FFmpegAACDecoder<LIBAV_VER>::DecodePacket(MP4Sample* aSample)
 {
   nsAutoPtr<AVFrame> frame(avcodec_alloc_frame());
   avcodec_get_frame_defaults(frame);
 
   AVPacket packet;
   av_init_packet(&packet);
 
+  aSample->Pad(FF_INPUT_BUFFER_PADDING_SIZE);
   packet.data = aSample->data;
   packet.size = aSample->size;
   packet.pos = aSample->byte_offset;
 
   int decoded;
   int bytesConsumed =
     avcodec_decode_audio4(&mCodecContext, frame.get(), &decoded, &packet);
 
--- a/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp
+++ b/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp
@@ -83,18 +83,21 @@ FFmpegDataDecoder<LIBAV_VER>::Init()
 
   // FFmpeg will call back to this to negotiate a video pixel format.
   mCodecContext.get_format = ChoosePixelFormat;
 
   mCodecContext.thread_count = PR_GetNumberOfProcessors();
   mCodecContext.thread_type = FF_THREAD_SLICE | FF_THREAD_FRAME;
   mCodecContext.thread_safe_callbacks = false;
 
+  mCodecContext.extradata_size = mExtraData.length();
+  for (int i = 0; i < FF_INPUT_BUFFER_PADDING_SIZE; i++) {
+    mExtraData.append(0);
+  }
   mCodecContext.extradata = mExtraData.begin();
-  mCodecContext.extradata_size = mExtraData.length();
 
   AVDictionary* opts = nullptr;
   if (avcodec_open2(&mCodecContext, codec, &opts) < 0) {
     NS_WARNING("Couldn't initialise ffmpeg decoder");
     return NS_ERROR_FAILURE;
   }
 
   if (mCodecContext.codec_type == AVMEDIA_TYPE_AUDIO &&
--- a/content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp
+++ b/content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp
@@ -48,16 +48,17 @@ FFmpegH264Decoder<LIBAV_VER>::Init()
 }
 
 void
 FFmpegH264Decoder<LIBAV_VER>::DecodeFrame(mp4_demuxer::MP4Sample* aSample)
 {
   AVPacket packet;
   av_init_packet(&packet);
 
+  aSample->Pad(FF_INPUT_BUFFER_PADDING_SIZE);
   packet.data = aSample->data;
   packet.size = aSample->size;
   packet.pts = aSample->composition_timestamp;
   packet.flags = aSample->is_sync_point ? AV_PKT_FLAG_KEY : 0;
   packet.pos = aSample->byte_offset;
 
   nsAutoPtr<AVFrame> frame(avcodec_alloc_frame());
   avcodec_get_frame_defaults(frame);
--- a/media/libstagefright/binding/DecoderData.cpp
+++ b/media/libstagefright/binding/DecoderData.cpp
@@ -124,16 +124,41 @@ MP4Sample::Update()
   duration = FindInt64(m, kKeyDuration);
   byte_offset = FindInt64(m, kKey64BitFileOffset);
   is_sync_point = FindInt32(m, kKeyIsSyncFrame);
   data = reinterpret_cast<uint8_t*>(mMediaBuffer->data());
   size = mMediaBuffer->range_length();
 }
 
 void
+MP4Sample::Pad(size_t aPaddingBytes)
+{
+  MOZ_ASSERT(data == mMediaBuffer->data());
+
+  size_t newSize = size + aPaddingBytes;
+
+  // If the existing MediaBuffer has enough space then we just recycle it. If
+  // not then we copy to a new buffer.
+  uint8_t* newData = mMediaBuffer && newSize <= mMediaBuffer->size()
+                       ? data
+                       : new uint8_t[newSize];
+
+  memset(newData + size, 0, aPaddingBytes);
+
+  if (newData != data) {
+    memcpy(newData, data, size);
+    extra_buffer = data = newData;
+    if (mMediaBuffer) {
+      mMediaBuffer->release();
+      mMediaBuffer = nullptr;
+    }
+  }
+}
+
+void
 MP4Sample::Prepend(const uint8_t* aData, size_t aSize)
 {
   size_t newSize = size + aSize;
 
   // If the existing MediaBuffer has enough space then we just recycle it. If
   // not then we copy to a new buffer.
   uint8_t* newData = mMediaBuffer && newSize <= mMediaBuffer->size()
                        ? data
--- a/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
@@ -75,16 +75,17 @@ public:
 };
 
 class MP4Sample
 {
 public:
   MP4Sample();
   ~MP4Sample();
   void Update();
+  void Pad(size_t aPaddingBytes);
 
   stagefright::MediaBuffer* mMediaBuffer;
 
   int64_t composition_timestamp;
   int64_t duration;
   int64_t byte_offset;
   bool is_sync_point;