- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 FFMPEG 中的 alpha channel 从 png 图像中编码视频(mov)。使用命令:
ffmpeg -i %d.png -r 25 -vcodec png -b:v 2500K out.mov -y
它运作良好。
[mov @ 0x29bf0c0] muxer does not support non seekable output
我在这样的代码中使用它:
oformat = av_guess_format("mov", nullptr, nullptr)
oformat->video_codec = AV_CODEC_ID_PNG;
ffmpeg 显示:
ffmpeg -h muxer=mov
Muxer mov [QuickTime / MOV]:
Common extensions: mov.
Default video codec: h264.
Default audio codec: aac.
默认的视频编解码器是 h264,但它可以使用上面的 ffmpeg 命令行使用 png 编码器创建 mov
ffmpeg -i out.mov
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'resa.mov':
Metadata:
major_brand : qt
minor_version : 512
compatible_brands: qt
encoder : Lavf59.24.100
Duration: 00:00:03.00, start: 0.000000, bitrate: 13430 kb/s
Stream #0:0: Video: png (png / 0x20676E70), rgba(pc), 1280x720, 13427 kb/s, 25 fps, 25 tbr, 12800 tbn, 12800 tbc (default)
Metadata:
handler_name : VideoHandler
vendor_id : FFMP
如何将此 cmd 更改为 c 代码?
ffmpeg -i %d.png -r 25 -vcodec png -b:v 2500K out.mov -y
我使用的代码:
#ifndef _RENDER_H_
#define _RENDER_H_
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <cstring>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <string>
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavcodec/avfft.h>
#include <libavdevice/avdevice.h>
#include <libavfilter/avfilter.h>
//#include <libavfilter/avfiltergraph.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavutil/opt.h>
#include <libavutil/common.h>
#include <libavutil/channel_layout.h>
#include <libavutil/imgutils.h>
#include <libavutil/mathematics.h>
#include <libavutil/samplefmt.h>
#include <libavutil/time.h>
#include <libavutil/opt.h>
#include <libavutil/pixdesc.h>
#include <libavutil/file.h>
//#include "libavcodec/vdpau.h"
#include "libavutil/hwcontext.h"
//#include "libavutil/hwcontext_vdpau.h"
#include <libswscale/swscale.h>
class VideoCapture {
public:
VideoCapture() {
oformat = nullptr;
ofctx = nullptr;
videoStream = nullptr;
videoFrame = nullptr;
swsCtx = nullptr;
frameCounter = 0;
av_register_all();
//av_log_set_callback(avlog_cb);
}
~VideoCapture() {
//Free();
}
void Init(std::string name, int width, int height, int fpsrate, int bitrate);
void AddFrame(uint8_t *data);
void Finish();
private:
AVOutputFormat *oformat;
AVFormatContext *ofctx;
AVIOContext *avio_out;
AVStream *videoStream;
AVFrame *videoFrame;
AVCodec *codec;
AVCodecContext *cctx;
struct buffer_data *bd;
struct buffer_data* res_video;
SwsContext *swsCtx;
//FILE *fp_write;
char* filename;
//int buf_len;
int frameCounter;
int fps;
void Free();
void Remux();
};
struct buffer_data {
uint8_t *ptr;
size_t size; ///< size left in the buffer
};
}
#endif
和代码:
#include "VideoCapture.h"
#define FINAL_FILE_NAME "record.mov"
#define VIDEO_TMP_FILE "tmp.avi"
using namespace std;
FILE *fp_write;
static int write_packet(void *opaque, uint8_t *buf, size_t buf_size)
{
struct buffer_data *bd = (struct buffer_data *)opaque;
printf("ptr :%p size:%zu\n", bd->ptr, bd->size);
memcpy(bd->ptr + bd->size, buf, buf_size);
bd->size = buf_size + bd->size;
return 1;
}
void VideoCapture::Init(string filename, int width, int height, int fpsrate, int bitrate) {
fps = fpsrate;
int err;
uint8_t *outbuffer=nullptr;
outbuffer=(uint8_t*)av_malloc(32768);
bd = (struct buffer_data*)malloc(sizeof(struct buffer_data));
bd->ptr = (uint8_t*)av_malloc(1000000000);
bd->size = 0;
avio_out =avio_alloc_context(outbuffer, 32768,1,bd,nullptr,write_packet,nullptr);
if (!(oformat = av_guess_format("mov", nullptr, nullptr))) {
cout << "Failed to define output format"<< endl;
return;
}
oformat->video_codec = AV_CODEC_ID_PNG;
cout << "oformat->video_codec " << oformat->video_codec << endl;
if ((err = avformat_alloc_output_context2(&ofctx, oformat, nullptr, nullptr) < 0)) {
cout <<"Failed to allocate output context"<< endl;
//Free();
return;
}
cout << "oformat->video_codec " << oformat->video_codec << endl;
if (!(codec = avcodec_find_encoder(oformat->video_codec))) {
cout <<"Failed to find encoder"<< endl;
//Free();
return;
}
if (!(videoStream = avformat_new_stream(ofctx, codec))) {
cout <<"Failed to create new stream"<< endl;
//Free();
return;
}
if (!(cctx = avcodec_alloc_context3(codec))) {
cout <<"Failed to allocate codec context"<< endl;
//Free();
return;
}
videoStream->codecpar->codec_id = oformat->video_codec;
videoStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
videoStream->codecpar->width = width;
videoStream->codecpar->height = height;
videoStream->codecpar->format = AV_PIX_FMT_RGBA;
videoStream->codecpar->bit_rate = bitrate * 1000;
videoStream->time_base = { 1, fps };
avcodec_parameters_to_context(cctx, videoStream->codecpar);
cctx->time_base = { 1, fps };
cctx->max_b_frames = 2;
cctx->gop_size = 12;
if (videoStream->codecpar->codec_id == AV_CODEC_ID_PNG) {
//av_opt_set(cctx, "preset", "ultrafast", 0);
}
if (ofctx->oformat->flags & AVFMT_GLOBALHEADER) {
cctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
avcodec_parameters_from_context(videoStream->codecpar, cctx);
if ((err = avcodec_open2(cctx, codec, nullptr)) < 0) {
cout <<"Failed to open codec"<< endl;
Free();
return;
}
ofctx->pb = avio_out;
ofctx->flags=AVFMT_FLAG_CUSTOM_IO;
if ((err = avformat_write_header(ofctx, nullptr)) < 0) {
cout <<"Failed to write header"<< endl;
Free();
return;
}
//av_dump_format(ofctx, 0, VIDEO_TMP_FILE, 1);
cout << "init com" << endl;
}
void VideoCapture::AddFrame(uint8_t *data) {
int err;
if (!videoFrame) {
videoFrame = av_frame_alloc();
videoFrame->format = AV_PIX_FMT_RGBA;
videoFrame->width = cctx->width;
videoFrame->height = cctx->height;
if ((err = av_frame_get_buffer(videoFrame, 32)) < 0) {
cout <<"Failed to allocate picture"<< endl;
return;
}
}
cout << "finish" << endl;
if (!swsCtx) {
swsCtx = sws_getContext(cctx->width, cctx->height, AV_PIX_FMT_RGBA, cctx->width, cctx->height, AV_PIX_FMT_RGBA, SWS_BICUBIC, 0, 0, 0);
}
int inLinesize[1] = { 4 * cctx->width};
sws_scale(swsCtx, (const uint8_t * const *)&data, inLinesize, 0, cctx->height, videoFrame->data, videoFrame->linesize);
videoFrame->pts = (1.0 / 30.0) * 90000 * (frameCounter++);;
if ((err = avcodec_send_frame(cctx, videoFrame)) < 0) {
cout <<"Failed to send frame"<< endl;
return;
}
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = nullptr;
pkt.size = 0;
if (avcodec_receive_packet(cctx, &pkt) == 0) {
pkt.flags |= AV_PKT_FLAG_KEY;
av_interleaved_write_frame(ofctx, &pkt);
av_packet_unref(&pkt);
}
}
void VideoCapture::Finish() {
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = nullptr;
pkt.size = 0;
for (;;) {
avcodec_send_frame(cctx, nullptr);
if (avcodec_receive_packet(cctx, &pkt) == 0) {
av_interleaved_write_frame(ofctx, &pkt);
av_packet_unref(&pkt);
}
else {
break;
}
}
av_write_trailer(ofctx);
/*
if (!(oformat->flags & AVFMT_NOFILE)) {
int err = avio_close(ofctx->pb);
if (err < 0) {
cout <<"Failed to close file"<< endl;
}
}
*/
fp_write = fopen(VIDEO_TMP_FILE, "wb");
if (!feof(fp_write)) {
int true_size = fwrite(bd->ptr, 1, bd->size, fp_write);
std::cout << true_size << std::endl;
}
fcloseall();
//Remux();
//Free();
}
void VideoCapture::Free() {
if (videoFrame) {
//std::cout << "videoFrame " << std::endl;
av_frame_free(&videoFrame);
}
if (cctx) {
//std::cout << "cctx" << std::endl;
avcodec_free_context(&cctx);
}
if (ofctx) {
//std::cout << "ofctx" << ofctx << std::endl;
avformat_free_context(ofctx);
}
if (swsCtx) {
//std::cout << "swsCtx" << std::endl;
sws_freeContext(swsCtx);
}
/*
if (bd->ptr != (void*)0)
{
free(bd->ptr);
}
free(bd);*/
}
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
{
struct buffer_data *bd = (struct buffer_data *)opaque;
buf_size = FFMIN(buf_size, bd->size);
if(buf_size == 0) return -1;
//printf("read ptr:%p size:%zu\n", bd->ptr, bd->size);
/* copy internal buffer data to buf */
memcpy(buf, bd->ptr, buf_size);
bd->ptr += buf_size;
bd->size -= buf_size;
return buf_size;
}
void VideoCapture::Remux() {
AVFormatContext *ifmt_ctx = nullptr, *ofmt_ctx = nullptr;
int err;
unsigned char* inbuffer=nullptr;
inbuffer=(unsigned char*)av_malloc(32768);
ifmt_ctx = avformat_alloc_context();
AVIOContext *avio_in =avio_alloc_context(inbuffer, 32768 ,0,bd,read_packet,nullptr,nullptr);
ifmt_ctx->pb=avio_in;
if (!(oformat = av_guess_format(nullptr, nullptr, "h264"))) {
cout << "Failed to define output format";
return;
}
if ((err = avformat_open_input(&ifmt_ctx, "nullptr", 0, 0)) < 0) {
cout <<"Failed to open input file for remuxing"<< endl;
}
if ((err = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
cout <<"Failed to retrieve input stream information"<< endl;
}
if ((err = avformat_alloc_output_context2(&ofmt_ctx, oformat, nullptr, nullptr))) {
cout <<"Failed to allocate output context"<< endl;
}
AVStream *inVideoStream = ifmt_ctx->streams[0];
AVStream *outVideoStream = avformat_new_stream(ofmt_ctx, nullptr);
if (!outVideoStream) {
cout <<"Failed to allocate output video stream" << endl;
}
outVideoStream->time_base = { 1, fps };
avcodec_parameters_copy(outVideoStream->codecpar, inVideoStream->codecpar);
outVideoStream->codecpar->codec_tag = 0;
uint8_t *outbuffer=nullptr;
outbuffer=(uint8_t*)av_malloc(32768);
res_video = (struct buffer_data*)malloc(sizeof(struct buffer_data));
res_video->ptr = (uint8_t*)av_malloc(100000000);
res_video->size = 0;
if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) {
avio_out =avio_alloc_context(outbuffer, 32768,1, res_video, nullptr, write_packet, nullptr);
ofmt_ctx->pb = avio_out;
}
AVDictionary* opts = nullptr;
av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
if ((err = avformat_write_header(ofmt_ctx, &opts)) < 0) {
cout <<"Failed to write header to output file"<< endl;
}
AVPacket videoPkt;
int ts = 0;
while (true) {
if ((err = av_read_frame(ifmt_ctx, &videoPkt)) < 0) {
break;
}
videoPkt.stream_index = outVideoStream->index;
videoPkt.pts = ts;
videoPkt.dts = ts;
videoPkt.duration = av_rescale_q(videoPkt.duration, inVideoStream->time_base, outVideoStream->time_base);
ts += videoPkt.duration;
videoPkt.pos = -1;
if ((err = av_interleaved_write_frame(ofmt_ctx, &videoPkt)) < 0) {
cout <<"Failed to mux packet"<< endl;
av_packet_unref(&videoPkt);
break;
}
av_packet_unref(&videoPkt);
}
av_write_trailer(ofmt_ctx);
cout << "res_video->size " << res_video->size << endl;
fp_write=fopen(FINAL_FILE_NAME,"wb");
if(!feof(fp_write)){
int true_size=fwrite(res_video->ptr,1, res_video->size,fp_write);
std::cout << true_size << std::endl;
}
fcloseall();
}
最佳答案
我已经解决了这个问题。 Ffmpeg 显示 muxer mov 支持视频编解码器 h264。所以我使用了支持vp9的webm。并且vp9支持yuva420p
Muxer webm [WebM]:
Common extensions: webm.
Mime type: video/webm.
Default video codec: vp9.
Default audio codec: vorbis.
Default subtitle codec: webvtt.
Encoder libvpx-vp9 [libvpx VP9]:
General capabilities: delay threads
Threading capabilities: other
Supported pixel formats: yuv420p yuva420p yuv422p yuv440p yuv444p yuv420p10le yuv422p10le yuv440p10le yuv444p10le yuv420p12le yuv422p12le yuv440p12le yuv444p12le gbrp gbrp10le gbrp12le
我更改代码
oformat = av_guess_format("mov", nullptr, nullptr)
至
oformat = av_guess_format("webm", nullptr, nullptr)
注意:解码webm时。原生 VP8/9 解码器不解码 alpha,但 libvpx 可以,并且 ffprobe 在可用时使用原生解码器作为流。目前,没有工具可以为流强制使用特定的解码器。因此您必须使用解码器 libvpx-vp9。像这样:
ffmpeg -vcodec libvpx-vp9 -i tmp.webm img_%04d.png
或在代码中:
AVCodec* pCodec = avcodec_find_decoder_by_name("libvpx-vp9");
见票:
关于c++ - 如何使用 ffmpeg 在 C 代码中从 png 中创建带有 alpha 的视频?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72527050/
我正在寻找一种经济合理的解决方案来长时间存储图片。我读到 PNG 文件格式,它与 JPEG 相比具有优越的特性,即在这些类别中: 无专利、无许可、无版税 无质量损失 尚未压缩 我有很多来自 Photo
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 9年前关闭。 Improve this q
我怎么能用 FFMEG 做到这一点? 输入 : 背景图片:background.png 图片帧列表:image_001.png,image_002.png ...(每张图片为一帧) 输出:所有帧都有背
$ cat png.ll ./packages/apps/Mms/res/mipmap-hdpi/ic_launcher_smsmms.png ./packages/apps/Mms/res/draw
这个问题在这里已经有了答案: Natural Sort Order in C# (18 个答案) 关闭 7 年前。 这是我的代码: private void Method1() { int
我一直在考虑用 Webp 图像替换我的 Android 应用程序中的 png 文件以减小 APK 大小。 虽然结果不错,但我想知道我是否使用了一些 png 转换器/压缩器,并且能够将尺寸减小到比我为
在 gnuplot-4.2.6 中,我可以使用 set term png medium x000000 xffffff set output 'file.png' plot x 这将生成一个带有黑色背
背景: 我正在努力使一堆 PNG 尽可能小。我正在使用诸如 PngOut、PngCrush 和 OptiPng 之类的工具。 问题: 我遇到了一个大小为 1434 KB 但只有 230 x 230 像
我正在使用 ImageMagick 调整图像大小。如果我传递 -resize WxH 选项,它会按预期运行。但是如果我通过 -resize WxH! (在调整大小时忽略纵横比),一些图像,尤其是 PN
如何访问/删除 PNG 元数据? 我正在寻找 Mac 应用程序或 PHP 代码段。 最佳答案 抱歉发布了一个 Windows 软件,但如果你没有找到任何对 MAC 有用的东西,那就是 TweakPNG
到目前为止似乎没有任何效果。我看到了 pnginfo以下消息: concept_Sjet_dream6.png... Image Width: 200 Image Length: 240 Bi
我有一个带有 Alpha channel (即透明度)的 PNG 图像,我需要创建将图像层合成到白色背景上的版本。我想使用可编写脚本的命令,使用 CLI 工具(例如 Image Magick)将 PN
我是初学者。我昨天问了一个类似的问题,但不知何故被否决了。所以这次我尽量简化问题。 带有 alpha png 的 24 位与 32 位 png 相同吗? 非常感谢您的一些提示。 最佳答案 没有“24
我有这个带点的荷兰 pdf 图像: pdf image of the netherlands with dots 当我尝试将此 pdf 转换为 png 图像时,使用 pdftools和 png像这样:
我在我的启动图像通用项目中添加了“Default.png,Default-568h@2x.png,Default@2x.png”这三个文件,我有三个不同的图像,分辨率与苹果中提到的完全相同文档,适用于
我在 Python 中使用 google app engine 并有几个静态 .png 图像文件,但它们都以“image/x-png”内容类型提供。这是一个问题,当我使用像 chrome 这样的浏览器
我做了一个 python 脚本,该脚本设法根据特定模式解散乱序(png)图像,该 python 脚本使用 ffmpeg 并进行 12 次编码来解乱它(通过裁剪特定部分并将其粘贴到现有图片上)。 因此,
我有一个 PNG 图像文件。我想将其转换为 GeoTiff。我安装了 QGIS 软件,但无法使用它,也不知道如何对图像进行地理配准。请帮我。有没有在线软件? 最佳答案 这是一个非常好的教程,其中包含有
我有一堆使用我编写的 Java 图表工具创建的图表 - 它们主要是黑白图表,带有浅绿色的块,偶尔还有其他颜色。它们当前被保存为 JPG 文件,我想将它们插入到我准备按需打印的书中。 这本书是一个 Op
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
我是一名优秀的程序员,十分优秀!