》视频编辑实现有以下几个方案:

ffmpeg+android/ios, 参考代码很多,跨平台。

openmax (AL编程) + android: openmx参考例子比较少,

gpuImage  开源ios框架,支持视频剪辑滤镜等功能;

参考:开源alure-1.2.tar  http://kcat.strangesoft.net/index.html

      demo:  <a target=_blank href="http://kcat.strangesoft.net/alffmpeg.c">http://kcat.strangesoft.net/alffmpeg.c</a>
/*
有一些demo参考,未测试,慎用
http://kcat.strangesoft.net/alffmpeg.c* This program is free software. It comes without any warranty, to* the extent permitted by applicable law. You can redistribute it* and/or modify it under the terms of the Do What The Fuck You Want* To Public License, Version 2, as published by Sam Hocevar. See* http://sam.zoy.org/wtfpl/COPYING for more details.*//* ChangeLog:* 1 - Initial program* 2 - Changed getAVAudioData to not always grab another packet before decoding*     to prevent buffering more compressed data than needed* 3 - Update to use avcodec_decode_audio3 and fix for decoders that need*     aligned output pointers* 4 - Fixed bits/channels format assumption* 5 - Improve time handling* 6 - Remove use of ALUT*/#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <assert.h>#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alext.h>#ifndef _WIN32
#include <unistd.h>
#define Sleep(x) usleep((x)*1000)
#else
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif/* Opaque handles to files and streams. The main app doesn't need to concern* itself with the internals */
typedef struct MyFile *FilePtr;
typedef struct MyStream *StreamPtr;#ifndef AL_SOFT_buffer_samples
/* Sample types */
#define AL_BYTE                                  0x1400
#define AL_UNSIGNED_BYTE                         0x1401
#define AL_SHORT                                 0x1402
#define AL_UNSIGNED_SHORT                        0x1403
#define AL_INT                                   0x1404
#define AL_UNSIGNED_INT                          0x1405
#define AL_FLOAT                                 0x1406
#define AL_DOUBLE                                0x1407/* Channel configurations */
#define AL_MONO                                  0x1500
#define AL_STEREO                                0x1501
#define AL_REAR                                  0x1502
#define AL_QUAD                                  0x1503
#define AL_5POINT1                               0x1504 /* (WFX order) */
#define AL_6POINT1                               0x1505 /* (WFX order) */
#define AL_7POINT1                               0x1506 /* (WFX order) */
#endif/**** Helper functions ****/#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>typedef struct PacketList {AVPacket pkt;struct PacketList *next;
} PacketList;struct MyStream {AVCodecContext *CodecCtx;int StreamIdx;PacketList *Packets;char *DecodedData;size_t DecodedDataSize;FilePtr parent;
};struct MyFile {AVFormatContext *FmtCtx;StreamPtr *Streams;size_t StreamsSize;
};/* This opens a file with ffmpeg and sets up the streams' information */
FilePtr openAVFile(const char *fname)
{static int done = 0;FilePtr file;/* We need to make sure ffmpeg is initialized. Optionally silence warning* output from the lib */if(!done) {av_register_all();av_log_set_level(AV_LOG_ERROR);done = 1;}file = (FilePtr)calloc(1, sizeof(*file));if(file && avformat_open_input(&file->FmtCtx, fname, NULL, NULL) == 0){/* After opening, we must search for the stream information because not* all formats will have it in stream headers */if(av_find_stream_info(file->FmtCtx) >= 0)return file;av_close_input_file(file->FmtCtx);}free(file);return NULL;
}/* This closes/frees an opened file and any of its streams. Pretty self-* explanitory... */
void closeAVFile(FilePtr file)
{size_t i;if(!file) return;for(i = 0;i < file->StreamsSize;i++){StreamPtr stream = file->Streams[i];while(stream->Packets){PacketList *self = stream->Packets;stream->Packets = self->next;av_free_packet(&self->pkt);av_free(self);}avcodec_close(stream->CodecCtx);av_free(stream->DecodedData);free(stream);}free(file->Streams);av_close_input_file(file->FmtCtx);free(file);
}/* This reports certain information from the file, eg, the number of audio* streams */
int getAVFileInfo(FilePtr file, int *numaudiostreams)
{unsigned int i;int audiocount = 0;if(!file) return 1;for(i = 0;i < file->FmtCtx->nb_streams;i++){if(file->FmtCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO)audiocount++;}*numaudiostreams = audiocount;return 0;
}/* This retrieves a handle for the given audio stream number (generally 0, but* some files can have multiple audio streams in one file) */
StreamPtr getAVAudioStream(FilePtr file, int streamnum)
{unsigned int i;if(!file) return NULL;for(i = 0;i < file->FmtCtx->nb_streams;i++){if(file->FmtCtx->streams[i]->codec->codec_type != CODEC_TYPE_AUDIO)continue;if(streamnum == 0){StreamPtr stream;AVCodec *codec;void *temp;size_t j;/* Found the requested stream. Check if a handle to this stream* already exists and return it if it does */for(j = 0;j < file->StreamsSize;j++){if(file->Streams[j]->StreamIdx == (int)i)return file->Streams[j];}/* Doesn't yet exist. Now allocate a new stream object and fill in* its info */stream = (StreamPtr)calloc(1, sizeof(*stream));if(!stream) return NULL;stream->parent = file;stream->CodecCtx = file->FmtCtx->streams[i]->codec;stream->StreamIdx = i;/* Try to find the codec for the given codec ID, and open it */codec = avcodec_find_decoder(stream->CodecCtx->codec_id);if(!codec || avcodec_open(stream->CodecCtx, codec) < 0){free(stream);return NULL;}/* Allocate space for the decoded data to be stored in before it* gets passed to the app */stream->DecodedData = av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);if(!stream->DecodedData){avcodec_close(stream->CodecCtx);free(stream);return NULL;}/* Append the new stream object to the stream list. The original* pointer will remain valid if realloc fails, so we need to use* another pointer to watch for errors and not leak memory */temp = realloc(file->Streams, (file->StreamsSize+1) *sizeof(*file->Streams));if(!temp){avcodec_close(stream->CodecCtx);av_free(stream->DecodedData);free(stream);return NULL;}file->Streams = (StreamPtr*)temp;file->Streams[file->StreamsSize++] = stream;return stream;}streamnum--;}return NULL;
}/* Returns information about the given audio stream. Returns 0 on success. */
int getAVAudioInfo(StreamPtr stream, ALuint *rate, ALenum *channels, ALenum *type)
{if(!stream || stream->CodecCtx->codec_type != CODEC_TYPE_AUDIO)return 1;if(type){if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_U8)*type = AL_UNSIGNED_BYTE;else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_S16)*type = AL_SHORT;else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_S32)*type = AL_INT;else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_FLT)*type = AL_FLOAT;else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_DBL)*type = AL_DOUBLE;elsereturn 1;}if(channels){if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_MONO)*channels = AL_MONO;else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_STEREO)*channels = AL_STEREO;else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_QUAD)*channels = AL_QUAD;else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1)*channels = AL_5POINT1;else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_7POINT1)*channels = AL_7POINT1;elsereturn 1;}if(rate) *rate = stream->CodecCtx->sample_rate;return 0;
}/* Used by getAV*Data to search for more compressed data, and buffer it in the* correct stream. It won't buffer data for streams that the app doesn't have a* handle for. */
static int getNextPacket(FilePtr file, int streamidx)
{PacketList *packet = (PacketList*)av_malloc(sizeof(PacketList));packet->next = NULL;next_pkt:while(av_read_frame(file->FmtCtx, &packet->pkt) >= 0){StreamPtr *iter = file->Streams;StreamPtr *iter_end = iter + file->StreamsSize;/* Check each stream the user has a handle for, looking for the one* this packet belongs to */while(iter != iter_end){if((*iter)->StreamIdx == packet->pkt.stream_index){PacketList **last = &(*iter)->Packets;while(*last != NULL)last = &(*last)->next;*last = packet;if((*iter)->StreamIdx == streamidx)return 1;packet = (PacketList*)av_malloc(sizeof(PacketList));packet->next = NULL;goto next_pkt;}iter++;}/* Free the packet and look for another */av_free_packet(&packet->pkt);}av_free(packet);return 0;
}/* The "meat" function. Decodes audio and writes, at most, length bytes into* the provided data buffer. Will only return less for end-of-stream or error* conditions. Returns the number of bytes written. */
int getAVAudioData(StreamPtr stream, void *data, int length)
{int dec = 0;if(!stream || stream->CodecCtx->codec_type != CODEC_TYPE_AUDIO)return 0;while(dec < length){/* If there's no decoded data, find some */if(stream->DecodedDataSize == 0){int size;int len;/* If there's no more input data, break and return what we have */if(!stream->Packets &&!getNextPacket(stream->parent, stream->StreamIdx))break;/* Decode some data, and check for errors */size = AVCODEC_MAX_AUDIO_FRAME_SIZE;while((len=avcodec_decode_audio3(stream->CodecCtx,(int16_t*)stream->DecodedData, &size,&stream->Packets->pkt)) == 0){PacketList *self;if(size > 0)break;self = stream->Packets;stream->Packets = self->next;av_free_packet(&self->pkt);av_free(self);if(!stream->Packets)break;}if(!stream->Packets)continue;if(len < 0)break;if(len > 0){if(len < stream->Packets->pkt.size){/* Move the remaining data to the front and clear the end* bits */int remaining = stream->Packets->pkt.size - len;memmove(stream->Packets->pkt.data,&stream->Packets->pkt.data[len],remaining);memset(&stream->Packets->pkt.data[remaining], 0,stream->Packets->pkt.size - remaining);stream->Packets->pkt.size -= len;}else{PacketList *self = stream->Packets;stream->Packets = self->next;av_free_packet(&self->pkt);av_free(self);}}/* Set the output buffer size */stream->DecodedDataSize = size;}if(stream->DecodedDataSize > 0){/* Get the amount of bytes remaining to be written, and clamp to* the amount of decoded data we have */size_t rem = length-dec;if(rem > stream->DecodedDataSize)rem = stream->DecodedDataSize;/* Copy the data to the app's buffer and increment */memcpy(data, stream->DecodedData, rem);data = (char*)data + rem;dec += rem;/* If there's any decoded data left, move it to the front of the* buffer for next time */if(rem < stream->DecodedDataSize)memmove(stream->DecodedData, &stream->DecodedData[rem],stream->DecodedDataSize - rem);stream->DecodedDataSize -= rem;}}/* Return the number of bytes we were able to get */return dec;
}/**** The main app ****//* Create a simple signal handler for SIGINT so ctrl-c cleanly exits. */
static volatile int quitnow = 0;
static void handle_sigint(int signum)
{quitnow = 1;signal(signum, SIG_DFL);
}/* Some helper functions to get the name from the channel and type enums. */
static const char *ChannelsName(ALenum chans)
{switch(chans){case AL_MONO: return "Mono";case AL_STEREO: return "Stereo";case AL_REAR: return "Rear";case AL_QUAD: return "Quadraphonic";case AL_5POINT1: return "5.1 Surround";case AL_6POINT1: return "6.1 Surround";case AL_7POINT1: return "7.1 Surround";}return "Unknown";
}static const char *TypeName(ALenum type)
{switch(type){case AL_BYTE: return "S8";case AL_UNSIGNED_BYTE: return "U8";case AL_SHORT: return "S16";case AL_UNSIGNED_SHORT: return "U16";case AL_INT: return "S32";case AL_UNSIGNED_INT: return "U32";case AL_FLOAT: return "Float32";case AL_DOUBLE: return "Float64";}return "Unknown";
}/* Define the number of buffers and buffer size (in bytes) to use. 3 buffers is* a good amount (one playing, one ready to play, another being filled). 32256* is a good length per buffer, as it fits 1, 2, 4, 6, 7, 8, 12, 14, 16, 24,* 28, and 32 bytes-per-frame sizes. */
#define NUM_BUFFERS 3
#define BUFFER_SIZE 32256int main(int argc, char **argv)
{/* The device and context handles to play with */ALCdevice *device;ALCcontext *ctx;/* Here are the buffers and source to play out through OpenAL with */ALuint buffers[NUM_BUFFERS];ALuint source;ALint state; /* This will hold the state of the source */ALbyte *data; /* A temp data buffer for getAVAudioData to write to and pass* to OpenAL with */int count; /* The number of bytes read from getAVAudioData */int i; /* An iterator for looping over the filenames *//* Print out usage if no file was specified */if(argc < 2){fprintf(stderr, "Usage: %s <filenames...>\n", argv[0]);return 1;}/* Set up our signal handler to run on SIGINT (ctrl-c) */if(signal(SIGINT, handle_sigint) == SIG_ERR){fprintf(stderr, "Unable to set handler for SIGINT!\n");return 1;}/* Open and initialize a device with default settings */device = alcOpenDevice(NULL);if(!device){fprintf(stderr, "Could not open a device!\n");return 1;}ctx = alcCreateContext(device, NULL);if(ctx == NULL || alcMakeContextCurrent(ctx) == ALC_FALSE){if(ctx != NULL)alcDestroyContext(ctx);alcCloseDevice(device);fprintf(stderr, "Could not set a context!\n");return 1;}/* Generate the buffers and source */alGenBuffers(NUM_BUFFERS, buffers);if(alGetError() != AL_NO_ERROR){alcMakeContextCurrent(NULL);alcDestroyContext(ctx);alcCloseDevice(device);fprintf(stderr, "Could not create buffers...\n");return 1;}alGenSources(1, &source);if(alGetError() != AL_NO_ERROR){alDeleteBuffers(NUM_BUFFERS, buffers);alcMakeContextCurrent(NULL);alcDestroyContext(ctx);alcCloseDevice(device);fprintf(stderr, "Could not create source...\n");return 1;}/* Set parameters so mono sources won't distance attenuate */alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE);alSourcei(source, AL_ROLLOFF_FACTOR, 0);if(alGetError() != AL_NO_ERROR){alDeleteSources(1, &source);alDeleteBuffers(NUM_BUFFERS, buffers);alcMakeContextCurrent(NULL);alcDestroyContext(ctx);alcCloseDevice(device);fprintf(stderr, "Could not set source parameters...\n");return 1;}data = malloc(BUFFER_SIZE);if(data == NULL){alDeleteSources(1, &source);alDeleteBuffers(NUM_BUFFERS, buffers);alcMakeContextCurrent(NULL);alcDestroyContext(ctx);alcCloseDevice(device);fprintf(stderr, "Could not create temp buffer...\n");return 1;}/* Play each file listed on the command line */for(i = 1;i < argc && !quitnow;i++){static ALenum old_format;static ALuint old_rate;/* The base time to use when determining the playback time from the* source. */static int64_t basetime;static int64_t filetime;/* Handles for the audio stream */FilePtr file;StreamPtr stream;/* The format of the output stream */ALenum format = 0;ALenum channels;ALenum type;ALuint rate;/* Open the file and get the first stream from it */file = openAVFile(argv[i]);stream = getAVAudioStream(file, 0);if(!stream){closeAVFile(file);fprintf(stderr, "Could not open audio in %s\n", argv[i]);continue;}/* Get the stream format, and figure out the OpenAL format. We use the* AL_EXT_MCFORMATS extension to provide output of Quad, 5.1, and 7.1* audio streams */if(getAVAudioInfo(stream, &rate, &channels, &type) != 0){closeAVFile(file);fprintf(stderr, "Error getting audio info for %s\n", argv[i]);continue;}if(type == AL_UNSIGNED_BYTE){if(channels == AL_MONO) format = AL_FORMAT_MONO8;else if(channels == AL_STEREO) format = AL_FORMAT_STEREO8;else if(alIsExtensionPresent("AL_EXT_MCFORMATS")){if(channels == AL_QUAD) format = alGetEnumValue("AL_FORMAT_QUAD8");else if(channels == AL_5POINT1) format = alGetEnumValue("AL_FORMAT_51CHN8");else if(channels == AL_7POINT1) format = alGetEnumValue("AL_FORMAT_71CHN8");}}else if(type == AL_SHORT){if(channels == AL_MONO) format = AL_FORMAT_MONO16;else if(channels == AL_STEREO) format = AL_FORMAT_STEREO16;else if(alIsExtensionPresent("AL_EXT_MCFORMATS")){if(channels == AL_QUAD) format = alGetEnumValue("AL_FORMAT_QUAD16");else if(channels == AL_5POINT1) format = alGetEnumValue("AL_FORMAT_51CHN16");else if(channels == AL_7POINT1) format = alGetEnumValue("AL_FORMAT_71CHN16");}}else if(type == AL_FLOAT && alIsExtensionPresent("AL_EXT_FLOAT32")){if(channels == AL_MONO) format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");else if(channels == AL_STEREO) format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");else if(alIsExtensionPresent("AL_EXT_MCFORMATS")){if(channels == AL_QUAD) format = alGetEnumValue("AL_FORMAT_QUAD32");else if(channels == AL_5POINT1) format = alGetEnumValue("AL_FORMAT_51CHN32");else if(channels == AL_7POINT1) format = alGetEnumValue("AL_FORMAT_71CHN32");}}else if(type == AL_DOUBLE && alIsExtensionPresent("AL_EXT_DOUBLE")){if(channels == AL_MONO) format = alGetEnumValue("AL_FORMAT_MONO_DOUBLE");else if(channels == AL_STEREO) format = alGetEnumValue("AL_FORMAT_STEREO_DOUBLE");}if(format == 0 || format == -1){closeAVFile(file);fprintf(stderr, "Unhandled format (%s, %s) for %s",ChannelsName(channels), TypeName(type), argv[i]);continue;}/* If the format of the last file matches the current one, we can skip* the initial load and let the processing loop take over (gap-less* playback!) */count = 1;if(format == old_format && rate == old_rate){/* When skipping the initial load of a file (because the previous* one is using the same exact format), just remove the length of* the previous file from the base. This is so the timing will be* from the beginning of this file, which won't start playing until* the next buffer to get queued does */basetime -= filetime;filetime = 0;}else{int j;/* Wait for the last song to finish playing */do {Sleep(10);alGetSourcei(source, AL_SOURCE_STATE, &state);} while(alGetError() == AL_NO_ERROR && state == AL_PLAYING);/* Rewind the source position and clear the buffer queue */alSourceRewind(source);alSourcei(source, AL_BUFFER, 0);/* Reset old variables */basetime = 0;filetime = 0;old_format = format;old_rate = rate;/* Fill and queue the buffers */for(j = 0;j < NUM_BUFFERS;j++){ALint size, numchans, numbits;/* Make sure we get some data to give to the buffer */count = getAVAudioData(stream, data, BUFFER_SIZE);if(count <= 0) break;/* Buffer the data with OpenAL and queue the buffer onto the* source */alBufferData(buffers[j], format, data, count, rate);alSourceQueueBuffers(source, 1, &buffers[j]);/* For each successful buffer queued, increment the filetime */alGetBufferi(buffers[j], AL_SIZE, &size);alGetBufferi(buffers[j], AL_CHANNELS, &numchans);alGetBufferi(buffers[j], AL_BITS, &numbits);filetime += size / numchans * 8 / numbits;}/* Now start playback! */alSourcePlay(source);if(alGetError() != AL_NO_ERROR){closeAVFile(file);fprintf(stderr, "Error starting playback...\n");continue;}}fprintf(stderr, "Playing %s (%s, %s, %dhz)\n", argv[i],TypeName(type), ChannelsName(channels), rate);while(count > 0 && !quitnow){/* Check if any buffers on the source are finished playing */ALint processed = 0;alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);if(processed == 0){/* All buffers are full. Check if the source is still playing.* If not, restart it, otherwise, print the time and rest */alGetSourcei(source, AL_SOURCE_STATE, &state);if(alGetError() != AL_NO_ERROR){fprintf(stderr, "\nError checking source state...\n");break;}if(state != AL_PLAYING){alSourcePlay(source);if(alGetError() != AL_NO_ERROR){closeAVFile(file);fprintf(stderr, "\nError restarting playback...\n");break;}}else{int64_t curtime = 0;if(basetime >= 0){ALint offset = 0;alGetSourcei(source, AL_SAMPLE_OFFSET, &offset);curtime = basetime + offset;}fprintf(stderr, "\rTime: %ld:%05.02f", (long)(curtime/rate/60),(float)(curtime%(rate*60))/(float)rate);Sleep(10);}continue;}/* Read the next chunk of data and refill the oldest buffer */count = getAVAudioData(stream, data, BUFFER_SIZE);if(count > 0){ALuint buf = 0;alSourceUnqueueBuffers(source, 1, &buf);if(buf != 0){ALint size, numchans, numbits;/* For each successfully unqueued buffer, increment the* base time. */alGetBufferi(buf, AL_SIZE, &size);alGetBufferi(buf, AL_CHANNELS, &numchans);alGetBufferi(buf, AL_BITS, &numbits);basetime += size / numchans * 8 / numbits;alBufferData(buf, format, data, count, rate);alSourceQueueBuffers(source, 1, &buf);alGetBufferi(buf, AL_SIZE, &size);alGetBufferi(buf, AL_CHANNELS, &numchans);alGetBufferi(buf, AL_BITS, &numbits);filetime += size / numchans * 8 / numbits;}if(alGetError() != AL_NO_ERROR){fprintf(stderr, " !!! Error buffering data !!!\n");break;}}}fprintf(stderr, "\rTime: %ld:%05.02f\n", (long)(filetime/rate/60),(float)(filetime%(rate*60))/(float)rate);/* All done with this file. Close it and go to the next */closeAVFile(file);}fprintf(stderr, "Done.\n");if(!quitnow){/* All data has been streamed in. Wait until the source stops playing it */do {Sleep(10);alGetSourcei(source, AL_SOURCE_STATE, &state);} while(alGetError() == AL_NO_ERROR && state == AL_PLAYING);}/* All files done. Delete the source and buffers, and close OpenAL */free(data);alDeleteSources(1, &source);alDeleteBuffers(NUM_BUFFERS, buffers);alcMakeContextCurrent(NULL);alcDestroyContext(ctx);alcCloseDevice(device);return 0;
}

纯android java api实现,其实底层也用的是openmax库。

》bitmapparse.cpp  定义bmp对象操作类:

支持bmp文件头、bmp头和数据的信息提取、将data封装成bmp文件。

》FFMpegMedia   ffmpeg最底层实现的基类class, 针对编解码和打开生成媒体文件对象,提供了系列基本ffmpeg方法:

初始化输入/出流,文件格式fmtCtx获取,获取/复制解码器codexCtx,

分配、读、解码pkt,包保存写入文件,frame类型判断,设置输入width,h,pixFmt等,

新建初始化aud/vid stream,打开、关闭ffmpeg api等。

》FFMpegVideo/Audio.cpp 是class FFMpegMedia的子类,扩充其。

只是提供了2个方法,将基类的virtual方法重构了下,如输出文件的ofmtCtx,oCodexCtx只带vid/aud专有信息,而不是basic class的公共信息。

》demux  定义FFMPegVideo class,针对文件对象,进行demux方法。

-->继承 FFMpegMedia basic class

》FFMpegAdapter  定义了几个公共方法。

RGBR/YUV Rotate90()图片数据旋转90度,

av_create_bmp, RGBR数据buf,生成bmp文件;

video_to_picture()/ picture_to_video(): 图片和视频文件的互相生成。

》FFMpegUtil    定义了static公共方法,

视频生成n张图片,

ffmpeg注册释放api,文件中查找类型流ID,codeId Guess,打开/关闭xxCtx,

audio,查找、选择sapleRate,channelLayout方法。

》FFMpegOperation 通过调用上面的类,对音视频,图片文件进行操作;

提供了音视频分离/合并,视频生成n张图片,图片格式互转(bmp/jpg,png)方法。

其中ConvertImage方法,支持任意图片格式互转;其原理是调用FFMpegMedia 基类对输入输出PIC进行解码编码,输出cdexCtx是根据文件名后缀,调用FFMpegParseImage 子类的saveFrame重构方法,保存解码文件。

》FFMpegImage, 继承FFMPegVideo class,对图片进行读写转码操作;

重构了基类viturl 方法: 初始化/设置codexCtx,   Read/SaveFrame根据img特性实现;

c++视频编辑代码小结相关推荐

  1. (八)批量视频处理、批量视频编辑、背景移除/去背景/换背景/抠图/抠像代码/实时抠图、实时抠像、人像去背景、背景消除、摄像头背景移除

    (八)批量视频处理.批量视频编辑.背景移除/去背景/换背景/抠图/抠像代码/实时抠图.实时抠像.人像去背景.背景消除.摄像头背景移除 当前短视频飞速发展,视频博主经常需要对大量视频进行编辑.处理,商用 ...

  2. IOS视频编辑功能详解上篇-添加水印

    前言 用代码在简单视频编辑中,主要就是加美颜.水印(贴图).视频截取.视频拼接.音视频的处理,在美颜中,使用GPUImage即可实现多种滤镜.磨皮美颜的功能,并且可以脸部识别实时美颜等功能,这个有很多 ...

  3. android+高仿视频录制,android高仿微信视频编辑页

    android高仿微信视频编辑页-视频多张图片提取 上一篇中介绍了有关视频提取图片的知识点,如果对这个不太了解 建议看下android提取视频多张图片和视频信息之前这篇. 这里实现的是仿微信的视频编辑 ...

  4. 视频编辑SDK---我们只提供API,任你自由设计炫酷的功能

    面对相对复杂的视频编辑处理技术,你是否束手无策? 在短视频应用中,有一定技术难度的视频编辑技术中,我们提出了一种全新的解决方法:画板和画笔. 短视频处理,用画板和画笔,就够了! 我们设计了极其简单易懂 ...

  5. 3dmax高版本转低版本插件_视频编辑干货资料:低版本打开高版本pr文件

    做视频编辑的朋友都会用到pr软件,它具有强大的视频编辑功能,为此做视频编辑的朋友经常从网上收集相关资料下载使用,也会碰到下载的资料往往比我们实际应用的pr软件版本要高,因此无法打开下载文件.碰到这种情 ...

  6. android sdk build-tools_从零开始仿写一个抖音App——视频编辑SDK开发(一)

    本文首发于微信公众号--世界上有意思的事,搬运转载请注明出处,否则将追究版权责任.交流qq群:859640274. 大家好久不见,又有一个多月没有发文章了.不知道还有哪些读者记得我的 从零开始仿写抖音 ...

  7. java视频编辑怎么实现_OpenGL 实现视频编辑中的转场效果

    转场介绍 转场效果是什么? 转场效果,简单来说就是两段视频之间的衔接过渡效果. 现在拍摄 vlog 的玩家越来越多,要是视频没有一两个炫酷的转场效果,都不好意思拿出来炫酷了. 那么如何在视频编辑软件中 ...

  8. android高仿微信视频编辑页-视频多张图片提取

    android高仿微信视频编辑页-视频多张图片提取 上一篇中介绍了有关视频提取图片的知识点,如果对这个不太了解 建议看下android提取视频多张图片和视频信息之前这篇. 这里实现的是仿微信的视频编辑 ...

  9. web多媒体技术在视频编辑场景的应用

    大家上午好,很高兴来到咱们腾讯LIVE开发者大会.我今天分享的web多媒体技术在视频编辑场景的应用是个非常有意思的主题,希望大家能有所收获. 首先介绍下自己,我是袁运辉,2010年就加入了腾讯,目前主 ...

最新文章

  1. BahdanauAttention与LuongAttention注意力机制简介
  2. 通过PHP前端后台交互/通过ajax前端后台交互/php基础传输数据应用/简单的留言版/简单的注册账户/简单的登录页/...
  3. 汽车自动泊车APA简介
  4. Boost:BOOST_VERIFY扩展的用法测试程序
  5. 官宣!阿里Blink和Flink合并计划出炉
  6. docker nginx:1.21.4
  7. 【转载】DNN6开源CMS
  8. 洛谷 P1454【圣诞夜的极光】
  9. android用单元测试的多,AndroidStudio中对Android应用进行单元测试InstrumentationTestCase...
  10. 【通信仿真】基于matlab蒙特卡罗算法2FSK系统抗噪声性能仿真【含Matlab源码 1632期】
  11. Nodejs express中创建ejs项目,解决express下默认创建jade,无法创建ejs问
  12. Endnote X8激活注册信息
  13. python分行政区域汇总_python:编写行政区域三级菜单(day 1)
  14. 【AI视野·今日CV 计算机视觉论文速览 第228期】Tue, 29 Jun 2021
  15. 名表依波路borel_依波路手表排名 依波路手表世界排名第几
  16. Java第一天笔记01——jdk8的安装与环境变量的配置
  17. 霍纳法则c语言算法代码,霍纳法则(Horner's rule)
  18. numpy.pad对图片进行填充
  19. 计算机仿真稿件没有消息,计算机核心期刊排名和投稿信息(2)
  20. Win7 64位静态过PG,文件修改记录,备忘

热门文章

  1. RatingBar使用
  2. C# 代码注册Dll文件
  3. C语言基础|选择结构例题
  4. 解决Log4j日志文件输出到了前一天的备份文件里
  5. selenium方法~设置为无头模式
  6. AE cc 2018 详细安装教程
  7. 运营商最新号码段 以及 手机号码的正则表达式判断
  8. LaTeX段落缩进简介
  9. MS08-067利用
  10. 计算机管理看板方式,Kanban|看板-现场管理-太友科技专业提供现场可视化整体解决方案...