Advertisement
alcantor

avconv Cedarx Implementation

Jun 27th, 2014
843
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 10.28 KB | None | 0 0
  1. diff --git a/libavcodec/cedarh264.c b/libavcodec/cedarh264.c
  2. new file mode 100755
  3. index 0000000..f7360c6
  4. --- /dev/null
  5. +++ b/libavcodec/cedarh264.c
  6. @@ -0,0 +1,219 @@
  7. +/*
  8. + * H.264 encoding using the cedarx library
  9. + * Copyright (C) 2014 Alcantor <alcantor@hotmail.com>
  10. + */
  11. +
  12. +#include "libavutil/internal.h"
  13. +#include "libavutil/opt.h"
  14. +#include "libavutil/mem.h"
  15. +#include "libavutil/pixdesc.h"
  16. +#include "libavutil/stereo3d.h"
  17. +#include "avcodec.h"
  18. +#include "internal.h"
  19. +
  20. +#include <float.h>
  21. +#include <math.h>
  22. +#include <stdio.h>
  23. +#include <stdlib.h>
  24. +#include <string.h>
  25. +#include <unistd.h>
  26. +
  27. +/*#define LOG_NDEBUG 0
  28. +#define LOG_TAG "venc-file"
  29. +#include "../sunxicedar/include/CDX_Debug.h"*/
  30. +#include "../sunxicedar/include/include_vencoder/venc.h"
  31. +#include "../sunxicedar/include/include_system/cedarx_hardware.h"
  32. +
  33. +typedef struct cedarh264Context {
  34. +       AVClass        *class;
  35. +       cedarv_encoder_t *venc_device;
  36. +       int64_t framecnt;
  37. +} cedarh264Context;
  38. +
  39. +static void fillBufferInterleavedChroma(const AVFrame *frame, enum AVPixelFormat pix_fmt, unsigned char * dstY, unsigned char * dstC){
  40. +       int i, j, size[4] = { 0 }, has_plane[4] = { 0 }, nb_chromaplane = 0;
  41. +       const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
  42. +
  43. +       for (i = 0; i < 4; i++){
  44. +               int h, s = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
  45. +               has_plane[desc->comp[i].plane] = 1;
  46. +                       h = (frame->height + (1 << s) - 1) >> s;
  47. +               size[i] = h * frame->linesize[i];
  48. +       }
  49. +
  50. +       for (i = 1; i < 4; i++) if(has_plane[i]) ++nb_chromaplane;
  51. +
  52. +       if(has_plane[0]) memcpy(dstY, frame->data[0], size[0]);
  53. +
  54. +       for (i = 1; i < 4 && has_plane[i]; i++) {
  55. +               for(j = 0; j < size[i]; ++j)
  56. +                       dstC[(j*nb_chromaplane)+i-1] = ++frame->data[i][j];
  57. +       }
  58. +}
  59. +
  60. +static int cedarh264_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame,
  61. +                      int *got_packet)
  62. +{
  63. +       cedarh264Context *c4 = avctx->priv_data;
  64. +
  65. +       /* Cedar variables */
  66. +       cedarv_encoder_t *venc_device = c4->venc_device;
  67. +       VencInputBuffer input_buffer;
  68. +       VencOutputBuffer output_buffer;
  69. +       int result;
  70. +       *got_packet = 0;
  71. +
  72. +       /* Don't try to read empty frame */
  73. +       if(frame == NULL) return 0;
  74. +
  75. +       /* Get alloc buffer */
  76. +       while(1) {
  77. +               result = c4->venc_device->ioctrl(c4->venc_device, VENC_CMD_GET_ALLOCATE_INPUT_BUFFER, &input_buffer);
  78. +               if(result == 0) {
  79. +                       av_log(avctx, AV_LOG_DEBUG, "Get alloc id copy to encoder, input_buffer: %x\n", input_buffer.id);
  80. +
  81. +                       /* Copy data */
  82. +                       fillBufferInterleavedChroma(frame, avctx->pix_fmt, input_buffer.addrvirY, input_buffer.addrvirC);
  83. +                       /*result = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height);
  84. +                       if(result < 0) return result;
  85. +                       result = avpicture_layout((const AVPicture *)frame, avctx->pix_fmt,
  86. +                               avctx->width, avctx->height, input_buffer.addrvirY, result); //frame->size);*/
  87. +
  88. +                       /* Flush */
  89. +                       c4->venc_device->ioctrl(c4->venc_device, VENC_CMD_FLUSHCACHE_ALLOCATE_INPUT_BUFFER, &input_buffer);
  90. +                       break;
  91. +               }
  92. +
  93. +               av_log(avctx, AV_LOG_WARNING, "No alloc input buffer right now\n");
  94. +               usleep(10*1000);
  95. +       }
  96. +
  97. +       /* Encode */
  98. +       result = venc_device->ioctrl(venc_device, VENC_CMD_ENCODE, &input_buffer);
  99. +       av_log(avctx, AV_LOG_DEBUG, "Encoder result: %d, input_buffer.id: %d\n", result, input_buffer.id);
  100. +
  101. +       /* Return the buffer to the alloc buffer quene after encoder */
  102. +       venc_device->ioctrl(venc_device, VENC_CMD_RETURN_ALLOCATE_INPUT_BUFFER, &input_buffer);
  103. +       if(result == 0) {
  104. +               memset(&output_buffer, 0, sizeof(VencOutputBuffer));
  105. +               result = venc_device->ioctrl(venc_device, VENC_CMD_GET_BITSTREAM, &output_buffer);
  106. +               if(result == 0) {
  107. +                       //av_log(avctx, AV_LOG_DEBUG, "Alloc packet\n");
  108. +                       result = ff_alloc_packet(pkt, output_buffer.size0+output_buffer.size1);
  109. +                       if(result < 0) return result;
  110. +                       //av_log(avctx, AV_LOG_DEBUG, "Copy from encoder\n");
  111. +                       memcpy(pkt->data, output_buffer.ptr0 ,output_buffer.size0);
  112. +                       if(output_buffer.size1) memcpy(&pkt->data[output_buffer.size0], output_buffer.ptr1 ,output_buffer.size1);
  113. +                       venc_device->ioctrl(venc_device, VENC_CMD_RETURN_BITSTREAM, &output_buffer);
  114. +                       pkt->pts = c4->framecnt;
  115. +                       pkt->dts = c4->framecnt++;
  116. +                       *got_packet = 1;
  117. +                       //av_log(avctx, AV_LOG_DEBUG, "Got packet\n");
  118. +               }
  119. +       } else av_log(avctx, AV_LOG_ERROR, "Encoder fatal error\n");
  120. +
  121. +       return 0;
  122. +}
  123. +
  124. +static av_cold int cedarh264_close(AVCodecContext *avctx)
  125. +{
  126. +       cedarh264Context *c4 = avctx->priv_data;
  127. +
  128. +       av_log(avctx, AV_LOG_INFO, "cedarx_hardware_exit\n");
  129. +
  130. +       /* Close Cedar */
  131. +       c4->venc_device->ioctrl(c4->venc_device, VENC_CMD_CLOSE, 0);
  132. +       c4->venc_device = NULL;
  133. +       cedarx_hardware_exit(0);
  134. +
  135. +       return 0;
  136. +}
  137. +
  138. +static av_cold int cedarh264_init(AVCodecContext *avctx)
  139. +{
  140. +       cedarh264Context *c4 = avctx->priv_data;
  141. +
  142. +       /* Cedar variables */
  143. +       VencBaseConfig base_cfg;
  144. +       VencAllocateBufferParam alloc_parm;
  145. +       VencSeqHeader header_data;
  146. +
  147. +       /* Cedar encoder configuration */
  148. +       base_cfg.codectype = VENC_CODEC_H264;
  149. +       base_cfg.framerate = 1.0d / av_q2d(avctx->time_base); //get_fps(avctx);
  150. +       base_cfg.input_width = avctx->width;
  151. +       base_cfg.input_height = avctx->height;
  152. +       base_cfg.dst_width = avctx->width; /* Output size same as input */
  153. +       base_cfg.dst_height = avctx->height;
  154. +       switch(avctx->pix_fmt){
  155. +               case AV_PIX_FMT_YUV420P: base_cfg.inputformat = VENC_PIXEL_YUV420; break;
  156. +               case AV_PIX_FMT_RGB32: base_cfg.inputformat = VENC_PIXEL_RGBA; break;
  157. +               default:
  158. +                       av_log(avctx, AV_LOG_FATAL, "Unsupported pixel format!\n");
  159. +                       return AVERROR(ENOSYS);
  160. +       }
  161. +       base_cfg.targetbitrate = avctx->bit_rate; /* Output bitrate */
  162. +
  163. +       /* Cedar Init */
  164. +       av_log(avctx, AV_LOG_INFO, "cedarx_hardware_init\n");
  165. +       alloc_parm.buffernum = 4;
  166. +       cedarx_hardware_init(0);
  167. +       c4->venc_device = cedarvEncInit();
  168. +       c4->venc_device->ioctrl(c4->venc_device, VENC_CMD_BASE_CONFIG, &base_cfg);
  169. +       c4->venc_device->ioctrl(c4->venc_device, VENC_CMD_ALLOCATE_INPUT_BUFFER, &alloc_parm);
  170. +       c4->venc_device->ioctrl(c4->venc_device, VENC_CMD_OPEN, 0);
  171. +
  172. +       av_log(avctx, AV_LOG_INFO, "Input Stream: %ix%i@%i fps encode at %i bits/s\n", base_cfg.input_width,
  173. +               base_cfg.input_height, base_cfg.framerate, base_cfg.targetbitrate);
  174. +
  175. +       /* Write h264 header */
  176. +       c4->venc_device->ioctrl(c4->venc_device, VENC_CMD_HEADER_DATA, &header_data);
  177. +       avctx->extradata = header_data.bufptr;
  178. +       avctx->extradata_size = header_data.length;
  179. +
  180. +       /* Avlib stuffs */
  181. +       c4->framecnt = 0;
  182. +
  183. +       /* Check width */
  184. +       if(avctx->width % 32 != 0){
  185. +               av_log(avctx, AV_LOG_FATAL, "Input width is not a multiple of 32!\n");
  186. +               return AVERROR(ENOSYS);
  187. +       }
  188. +
  189. +       return 0;
  190. +}
  191. +
  192. +static av_cold void cedarh264_init_static(AVCodec *codec)
  193. +{
  194. +
  195. +}
  196. +
  197. +static const AVOption options[] = {
  198. +    { NULL },
  199. +};
  200. +
  201. +static const AVClass class = {
  202. +    .class_name = "cedarh264enc",
  203. +    .item_name  = av_default_item_name,
  204. +    .option     = options,
  205. +    .version    = LIBAVUTIL_VERSION_INT,
  206. +};
  207. +
  208. +static const AVCodecDefault cedarh264_defaults[] = {
  209. +    { NULL },
  210. +};
  211. +
  212. +AVCodec ff_cedarh264_encoder = {
  213. +    .name             = "cedarh264",
  214. +    .long_name        = NULL_IF_CONFIG_SMALL("SUNXI Cedar H.264 Encoder"),
  215. +    .type             = AVMEDIA_TYPE_VIDEO,
  216. +    .id               = AV_CODEC_ID_H264,
  217. +    .priv_data_size   = sizeof(cedarh264Context),
  218. +    .init             = cedarh264_init,
  219. +    .encode2          = cedarh264_frame,
  220. +    .close            = cedarh264_close,
  221. +    .capabilities     = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS,
  222. +    .priv_class       = &class,
  223. +    .defaults         = cedarh264_defaults,
  224. +    .init_static_data = cedarh264_init_static,
  225. +};
  226. diff --git a/configure b/configure
  227. index baec975..d4b4fb6 100755
  228. --- a/configure
  229. +++ b/configure
  230. @@ -1167,6 +1167,7 @@ EXTERNAL_LIBRARY_LIST="
  231.      openssl
  232.      x11grab
  233.      zlib
  234. +    vencoder
  235.  "
  236.  
  237.  FEATURE_LIST="
  238. @@ -1992,6 +1993,7 @@ libx264_encoder_deps="libx264"
  239.  libx265_encoder_deps="libx265"
  240.  libxavs_encoder_deps="libxavs"
  241.  libxvid_encoder_deps="libxvid"
  242. +cedarh264_encoder_extralibs="-lvencoder -ldl -L./sunxicedar/lib/A20"
  243.  
  244.  # demuxers / muxers
  245.  ac3_demuxer_select="ac3_parser"
  246. diff --git a/libavcodec/Makefile b/libavcodec/Makefile
  247. old mode 100644
  248. new mode 100755
  249. index 90c88c3..cca98ad
  250. --- a/libavcodec/Makefile
  251. +++ b/libavcodec/Makefile
  252. @@ -632,6 +632,8 @@ OBJS-$(CONFIG_LIBX264_ENCODER)            += libx264.o
  253.  OBJS-$(CONFIG_LIBX265_ENCODER)            += libx265.o
  254.  OBJS-$(CONFIG_LIBXAVS_ENCODER)            += libxavs.o
  255.  OBJS-$(CONFIG_LIBXVID_ENCODER)            += libxvid.o
  256. +OBJS-$(CONFIG_LIBX264_ENCODER)            += libx264.o
  257. +OBJS-$(CONFIG_CEDARH264_ENCODER)          += cedarh264.o
  258.  
  259.  # parsers
  260.  OBJS-$(CONFIG_AAC_PARSER)              += aac_parser.o aac_ac3_parser.o \
  261. diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
  262. old mode 100644
  263. new mode 100755
  264. index bd74e0b..187a097
  265. --- a/libavcodec/allcodecs.c
  266. +++ b/libavcodec/allcodecs.c
  267. @@ -459,6 +459,7 @@ void avcodec_register_all(void)
  268.      REGISTER_ENCODER(LIBX265,           libx265);
  269.      REGISTER_ENCODER(LIBXAVS,           libxavs);
  270.      REGISTER_ENCODER(LIBXVID,           libxvid);
  271. +    REGISTER_ENCODER(CEDARH264,         cedarh264);
  272.  
  273.      /* parsers */
  274.      REGISTER_PARSER(AAC,                aac);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement