linux/drivers/media/platform/coda/coda-h264.c
<<
>>
Prefs
   1/*
   2 * Coda multi-standard codec IP - H.264 helper functions
   3 *
   4 * Copyright (C) 2012 Vista Silicon S.L.
   5 *    Javier Martin, <javier.martin@vista-silicon.com>
   6 *    Xavier Duret
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/string.h>
  16#include <linux/videodev2.h>
  17#include <coda.h>
  18
  19static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 };
  20
  21static const u8 *coda_find_nal_header(const u8 *buf, const u8 *end)
  22{
  23        u32 val = 0xffffffff;
  24
  25        do {
  26                val = val << 8 | *buf++;
  27                if (buf >= end)
  28                        return NULL;
  29        } while (val != 0x00000001);
  30
  31        return buf;
  32}
  33
  34int coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb)
  35{
  36        const u8 *buf = vb2_plane_vaddr(vb, 0);
  37        const u8 *end = buf + vb2_get_plane_payload(vb, 0);
  38
  39        /* Find SPS header */
  40        do {
  41                buf = coda_find_nal_header(buf, end);
  42                if (!buf)
  43                        return -EINVAL;
  44        } while ((*buf++ & 0x1f) != 0x7);
  45
  46        ctx->params.h264_profile_idc = buf[0];
  47        ctx->params.h264_level_idc = buf[2];
  48
  49        return 0;
  50}
  51
  52int coda_h264_filler_nal(int size, char *p)
  53{
  54        if (size < 6)
  55                return -EINVAL;
  56
  57        p[0] = 0x00;
  58        p[1] = 0x00;
  59        p[2] = 0x00;
  60        p[3] = 0x01;
  61        p[4] = 0x0c;
  62        memset(p + 5, 0xff, size - 6);
  63        /* Add rbsp stop bit and trailing at the end */
  64        p[size - 1] = 0x80;
  65
  66        return 0;
  67}
  68
  69int coda_h264_padding(int size, char *p)
  70{
  71        int nal_size;
  72        int diff;
  73
  74        diff = size - (size & ~0x7);
  75        if (diff == 0)
  76                return 0;
  77
  78        nal_size = coda_filler_size[diff];
  79        coda_h264_filler_nal(nal_size, p);
  80
  81        return nal_size;
  82}
  83
  84int coda_h264_profile(int profile_idc)
  85{
  86        switch (profile_idc) {
  87        case 66: return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
  88        case 77: return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
  89        case 88: return V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED;
  90        case 100: return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
  91        default: return -EINVAL;
  92        }
  93}
  94
  95int coda_h264_level(int level_idc)
  96{
  97        switch (level_idc) {
  98        case 10: return V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
  99        case 9:  return V4L2_MPEG_VIDEO_H264_LEVEL_1B;
 100        case 11: return V4L2_MPEG_VIDEO_H264_LEVEL_1_1;
 101        case 12: return V4L2_MPEG_VIDEO_H264_LEVEL_1_2;
 102        case 13: return V4L2_MPEG_VIDEO_H264_LEVEL_1_3;
 103        case 20: return V4L2_MPEG_VIDEO_H264_LEVEL_2_0;
 104        case 21: return V4L2_MPEG_VIDEO_H264_LEVEL_2_1;
 105        case 22: return V4L2_MPEG_VIDEO_H264_LEVEL_2_2;
 106        case 30: return V4L2_MPEG_VIDEO_H264_LEVEL_3_0;
 107        case 31: return V4L2_MPEG_VIDEO_H264_LEVEL_3_1;
 108        case 32: return V4L2_MPEG_VIDEO_H264_LEVEL_3_2;
 109        case 40: return V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
 110        case 41: return V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
 111        default: return -EINVAL;
 112        }
 113}
 114