WebM是Google提出的新的网络视频格式,本质上是个MKV的壳,封装VPX中的VP8视频流与Vorbis OGG音频流。目前Firefox、Opera、Chrome都能直接打开WebM视频文件而无需其他任何乱七八糟的插件。我个人倒是很喜欢WebM的OGG音频,虽然在低比特率下不如AAC,不过依旧胜过MP3太多了。

最近接手了一个项目,将Showcase中的Flash视频导出替换为WebM视频导出,着实蛋疼了一把,因为ffmpeg这个破玩意的最新二进制版本虽然集成了VPX,不过由于许可证等等原因,商业软件不好直接使用。一气之下我直接用Google提供的WebM SDK搞定从序列帧到视频的输出,完全摆脱ffmpeg。

对于WebM SDK我了找到的三个问题:

  • 依旧没有内建RGB24到YV12的转换,不得不手动来。
  • SDK提供的simple_encoder产生出的IVF依旧无法播放。
  • 如果构造了一个YV12格式的vpx_image_t对象,这个对象无法重复使用,产生的视频有错。

下面是我的WebMEnc编码器主文件的代码,不明白的WebM SDK如何使用的朋友可以学习一下。JPEG、TIFF、PNG的读取使用了FreeImage。

完整的代码在Ortholab的SVN里有。

可执行二进制程序可以在这里下载。

// Copyright (c) 2011 Bo Zhou<Bo.Schwarzstein@gmail.com>
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.#include <stdio.h>
#include <stdlib.h>#include <FreeImage.h>#include <vpx/vpx_codec.h>
#include <vpx/vpx_encoder.h>
#include <vpx/vpx_image.h>
#include <vpx/vpx_version.h>#include <vpx/vp8cx.h>#include "EbmlWriter.h"#define rgbtoy(b, g, r, y) \
y=(unsigned char)(((int)(30*r) + (int)(59*g) + (int)(11*b))/100)#define rgbtoyuv(b, g, r, y, u, v) \
rgbtoy(b, g, r, y); \
u=(unsigned char)(((int)(-17*r) - (int)(33*g) + (int)(50*b)+12800)/100); \
v=(unsigned char)(((int)(50*r) - (int)(42*g) - (int)(8*b)+12800)/100)#if defined(_MSC_VER)
/* MSVS doesn't define off_t, and uses _f{seek,tell}i64 */
#define fseeko _fseeki64
#define ftello _ftelli64
#endifvoid rgb2YUV420P(vpx_image_t *rgbImage, vpx_image_t *yv12Image)
{unsigned int width = rgbImage->w;unsigned int height = rgbImage->h;unsigned int planeSize = width * height;unsigned int halfWidth = width >> 1;unsigned char* yPlane = yv12Image->img_data;unsigned char* uPlane = yPlane + planeSize;unsigned char* vPlane = uPlane + (planeSize >> 2);static const int rgbIncrement = 3;unsigned char* rgb = rgbImage->img_data;for (unsigned int y = 0; y < height; ++ y){unsigned char* yLine = yPlane + (y * width);unsigned char* uLine = uPlane + ((y >> 1) * halfWidth);unsigned char* vLine = vPlane + ((y >> 1) * halfWidth);for (unsigned int x = 0; x < width; x += 2){rgbtoyuv(rgb[2], rgb[1], rgb[0], *yLine, *uLine, *vLine);rgb += rgbIncrement;yLine++;rgbtoyuv(rgb[2], rgb[1], rgb[0], *yLine, *uLine, *vLine);rgb += rgbIncrement;yLine++;uLine++;vLine++;}}
}bool readImage(char *filename, int frameNumber, vpx_image_t **pRGBImage, vpx_image_t **pYV12Image)
{// Load image.//char path[512];sprintf(path, filename, frameNumber);FREE_IMAGE_FORMAT format = FIF_UNKNOWN;format = FreeImage_GetFIFFromFilename(filename);if ( (format == FIF_UNKNOWN) ||((format != FIF_JPEG) &&(format != FIF_TIFF) &&(format != FIF_PNG)) ){return false;}FIBITMAP* dib = FreeImage_Load(format, path);if (dib == NULL){return false;}unsigned w = FreeImage_GetWidth(dib);unsigned h = FreeImage_GetHeight(dib);if (*pRGBImage == NULL){*pRGBImage = vpx_img_alloc(NULL, VPX_IMG_FMT_RGB24, w, h, 1);}if (*pYV12Image == NULL){*pYV12Image = vpx_img_alloc(NULL, VPX_IMG_FMT_YV12, w, h, 1);}memcpy((*pRGBImage)->img_data, FreeImage_GetBits(dib), w * h * 3);rgb2YUV420P(*pRGBImage, *pYV12Image);vpx_img_flip(*pYV12Image);FreeImage_Unload(dib);return true;
}int main(int argc, char* argv[])
{if (argc != 4){printf("  Usage: WebMEnc <filename> <bit-rates> <output file>\nExample: WebMEnc frame.%%.5d.jpg 512 frame.webm\n");return EXIT_FAILURE;}#ifdef FREEIMAGE_LIBFreeImage_Initialise();
#endif// Initialize VPX codec.//vpx_codec_ctx_t vpxContext;vpx_codec_enc_cfg_t vpxConfig;if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &vpxConfig, 0) != VPX_CODEC_OK){return EXIT_FAILURE;}// Try to load the first frame to initialize width and height.//vpx_image_t *rgbImage = NULL, *yv12Image = NULL;if (readImage(argv[1], 0, &rgbImage, &yv12Image) == false){return EXIT_FAILURE;}vpxConfig.g_h = yv12Image->h;vpxConfig.g_w = yv12Image->w;vpxConfig.rc_target_bitrate = atoi(argv[2]);vpxConfig.g_threads = 2;// Prepare the output .webm file.//EbmlGlobal ebml;memset(&ebml, 0, sizeof(EbmlGlobal));ebml.last_pts_ms = -1;ebml.stream = fopen(argv[3], "wb");if (ebml.stream == NULL){return EXIT_FAILURE;}vpx_rational ebmlFPS = vpxConfig.g_timebase;struct vpx_rational arg_framerate = {30, 1};Ebml_WriteWebMFileHeader(&ebml, &vpxConfig, &arg_framerate);if (vpx_codec_enc_init(&vpxContext, vpx_codec_vp8_cx(), &vpxConfig, 0) != VPX_CODEC_OK){return EXIT_FAILURE;}// Reading image file sequence, encoding to .WebM file.//int frameNumber = 0;while(readImage(argv[1], frameNumber, &rgbImage, &yv12Image)){vpx_codec_err_t vpxError = vpx_codec_encode(&vpxContext, yv12Image, frameNumber, 33, 0, 0);if (vpxError != VPX_CODEC_OK){return EXIT_FAILURE;}vpx_codec_iter_t iter = NULL;const vpx_codec_cx_pkt_t *packet;while( (packet = vpx_codec_get_cx_data(&vpxContext, &iter)) ){Ebml_WriteWebMBlock(&ebml, &vpxConfig, packet);}frameNumber ++;printf("Processed %d frames.\r", frameNumber);vpx_img_free(yv12Image);yv12Image = NULL;}Ebml_WriteWebMFileFooter(&ebml, 0);fclose(ebml.stream);vpx_codec_destroy(&vpxContext);#ifdef FREEIMAGE_LIBFreeImage_DeInitialise();
#endifreturn EXIT_SUCCESS;
}

WebM VP8 SDK Usage/关于WebM VP8 SDK的用法相关推荐

  1. iSpring SDK 10 Crack!iSpring SDK NEW @ 2022定格!

    iSpring SDK-------5.7.0到  10.0版本 iSpring SDK(软件开发工具包)是一种高性能解决方案,可为网站和在线应用程序提供自动 PowerPoint 到 HTML 5 ...

  2. 提升普适性,阿里云官方SDK发布支持Go语言SDK

    摘要: 日前,阿里云官方SDK发布支持新语言--Go 语言SDK,意味着90%以上产品可以随时生成并发布Go SDK,给Go语言的开发者使用. 此次阿里云发布支持Go SDK的新功能,可以让Go语言开 ...

  3. python的sdk是什么意思_python sdk

    关于 python sdk的搜索结果 问题 命令行工具 CLI:用户指南:阿里云 Python SDK 列表 阿里云各产品对应的 Python SDK 如下所示. 产品Python SDK账号登录al ...

  4. android sdk所有版本下载,android sdk全平台版本集成

    这是android sdk 全平台版本集成下载,谷歌经常被墙,有的同学也不知道如何下载平台环境,所以特意把全平台工具环境打包上来,方便大家下载. 软件介绍 android sdk全平台版本集成是一个管 ...

  5. 什么是美颜SDK?怎样选择美颜SDK?

    如今人们通过互联网就可以足不出户收获更多的知识.获取更多的讯息,同时也能得到更多快乐,例如直播和短视频平台.它们的竞相出场,让人们的视野得到了进一步开阔,同时也打造了"颜值经济". ...

  6. Unity和AndroidStudio交互制作SDK并和其他的SDK合并(微信APP支付)

    本案例使用的AndroidStudio版本为 171.4408382 Unity版本为 5.2.4f1 如果跟我一样是新手,就请先看我下面这篇文章 https://blog.csdn.net/weix ...

  7. 【初学者】SDK的理解(客户端SDK和服务器端SDK)

    数据采集层(SDK) 1.何为SDK? 1.1.定义 SDK是指一种软件开发工具包,是数据采集的必备工具,英文为"Software Development Kit".本质上它其实是 ...

  8. Unity接入微信SDK——iOS(接入微信SDK)

    Unity接入微信SDK--iOS(一 接入微信SDK) 下载微信SDK 下载地址:微信开放平台 导出Unity Xcode项目 导出Unity Xcode项目,并打开 微信SDK导入Xcode项目 ...

  9. 使用迅雷代替SDK Manager加速下载Android SDK

    使用SDK Manager(即Android SDK and AVD Manager)下载Android SDK相关文件非常地慢, 用AVD Manager升级SDK时,会在线升级,会很慢很慢,在升级 ...

最新文章

  1. Linux进程描述符task_struct结构体简析
  2. spring框架四大原则
  3. Sublime Text2 快捷键汇总
  4. Spark详解(六):Spark集群资源调度算法原理
  5. Mysql商品和图片表_【mysql】数据库设计模式:多个图片怎么和商品关联
  6. Java学习(三)面向对象异常
  7. 我们和计算机系的老教授聊了聊TCP优化与产学矛盾
  8. 计算机网络df例题,计算机网络期末试题北交.doc
  9. RTX5 | 内存池01 - 内存池的使用
  10. 我希望早几年知道的5个Unix命令
  11. linux除法脚本,经典shell-脚本实例
  12. Android 记住账号密码+自动登录
  13. java - EM算法
  14. 完美解决异常问题UnicodeEncodeError: ‘ascii‘ codec can‘t encode characters in position 0-7: ordinal not in ra
  15. git分支主干同步命令
  16. 【精选】基于EasyX的贪吃蛇小游戏
  17. ug900-vivado-logic-simulation中文文档 | Xilinx
  18. 服务器修改mysql登录密码忘了怎么办,云服务器mysql密码重置密码忘记了
  19. 关于BBS的一些资料
  20. 最新AUTO病毒变种(Win32.Troj.AutoRun.te.v)的分析和解决方案

热门文章

  1. scala语言示例_var关键字与Scala中的示例
  2. c ++查找字符串_C ++数组| 查找输出程序| 套装5
  3. 软件工程 软件设计 步骤_好的软件设计特点 软件工程
  4. 第十三章 数据库支持
  5. librtmp分析(发送数据包处理)
  6. 微信小程序数据拼接_微信小程序 数据预拉取
  7. Java开发环境!我总结了所有面试题
  8. java中的几种泛型类——HashSet、HashMap、TreeSet、TreeMap,遍历map,排序,HashTable比较
  9. 小程序 setData 中的坑,其实好像...
  10. linux 单用户密码修改