15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/mp4/avc.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/mp4/box_definitions.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/mp4/box_reader.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace mp4 {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const uint8 kAnnexBStartCode[] = {0, 0, 0, 1};
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kAnnexBStartCodeSize = 4;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool ConvertAVCToAnnexBInPlaceForLengthSize4(std::vector<uint8>* buf) {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kLengthSize = 4;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t pos = 0;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (pos + kLengthSize < buf->size()) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nal_size = (*buf)[pos];
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nal_size = (nal_size << 8) + (*buf)[pos+1];
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nal_size = (nal_size << 8) + (*buf)[pos+2];
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nal_size = (nal_size << 8) + (*buf)[pos+3];
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::copy(kAnnexBStartCode, kAnnexBStartCode + kAnnexBStartCodeSize,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              buf->begin() + pos);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos += kLengthSize + nal_size;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pos == buf->size();
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AVC::ConvertFrameToAnnexB(int length_size, std::vector<uint8>* buffer) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RCHECK(length_size == 1 || length_size == 2 || length_size == 4);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (length_size == 4)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ConvertAVCToAnnexBInPlaceForLengthSize4(buffer);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<uint8> temp;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  temp.swap(*buffer);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer->reserve(temp.size() + 32);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t pos = 0;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (pos + length_size < temp.size()) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nal_size = temp[pos];
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (length_size == 2) nal_size = (nal_size << 8) + temp[pos+1];
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos += length_size;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RCHECK(pos + nal_size <= temp.size());
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer->insert(buffer->end(), kAnnexBStartCode,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   kAnnexBStartCode + kAnnexBStartCodeSize);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer->insert(buffer->end(), temp.begin() + pos,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   temp.begin() + pos + nal_size);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos += nal_size;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pos == temp.size();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AVC::ConvertConfigToAnnexB(
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AVCDecoderConfigurationRecord& avc_config,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<uint8>* buffer) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buffer->empty());
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer->clear();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int total_size = 0;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < avc_config.sps_list.size(); i++)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total_size += avc_config.sps_list[i].size() + kAnnexBStartCodeSize;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < avc_config.pps_list.size(); i++)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total_size += avc_config.pps_list[i].size() + kAnnexBStartCodeSize;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer->reserve(total_size);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < avc_config.sps_list.size(); i++) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer->insert(buffer->end(), kAnnexBStartCode,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                kAnnexBStartCode + kAnnexBStartCodeSize);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer->insert(buffer->end(), avc_config.sps_list[i].begin(),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                avc_config.sps_list[i].end());
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < avc_config.pps_list.size(); i++) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer->insert(buffer->end(), kAnnexBStartCode,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   kAnnexBStartCode + kAnnexBStartCodeSize);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer->insert(buffer->end(), avc_config.pps_list[i].begin(),
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   avc_config.pps_list[i].end());
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace mp4
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
92