Ffmpeg 将原始yuv转换为在android上崩溃的mp4
以下是我的步骤:Ffmpeg 将原始yuv转换为在android上崩溃的mp4,ffmpeg,yuv,Ffmpeg,Yuv,以下是我的步骤: 将jpeg文件解码为rgb565;(成功) 将rgb565转换为yuv420;(不确定是否有效,函数“Bitmap2Yuv420”) 将yuv420转换为mp4。(调用avcodec_open2时崩溃) 这就是代码: void ADKJpegDecoder::Bitmap2Yuv420(const char * outfilename) { unsigned char *destination = new unsigned char[m_Width * m_Height
void ADKJpegDecoder::Bitmap2Yuv420(const char * outfilename) {
unsigned char *destination = new unsigned char[m_Width * m_Height
* m_BytesPerPixel / 2];
unsigned char* rgb = m_RawImage;
size_t image_size = m_Width * m_Height;
size_t upos = image_size;
size_t vpos = upos + upos / 4;
size_t i = 0;
for (size_t line = 0; line < m_Height; ++line) {
if (!(line % 2)) {
for (size_t x = 0; x < m_Width; x += 2) {
char r = rgb[3 * i];
char g = rgb[3 * i + 1];
char b = rgb[3 * i + 2];
destination[i++] = ((66 * r + 129 * g + 25 * b) >> 8) + 16;
destination[upos++] = ((-38 * r + -74 * g + 112 * b) >> 8)
+ 128;
destination[vpos++] = ((112 * r + -94 * g + -18 * b) >> 8)
+ 128;
r = rgb[3 * i];
g = rgb[3 * i + 1];
b = rgb[3 * i + 2];
destination[i++] = ((66 * r + 129 * g + 25 * b) >> 8) + 16;
}
} else {
for (size_t x = 0; x < m_Width; x += 1) {
char r = rgb[3 * i];
char g = rgb[3 * i + 1];
char b = rgb[3 * i + 2];
destination[i++] = ((66 * r + 129 * g + 25 * b) >> 8) + 16;
}
}
}
ADKVideoEncoder::getInstance()->startEncodeVideo(destination);
delete[] destination;
void ADKJpegDecoder::Bitmap2Yuv420(常量字符*outfilename){
无符号字符*目的地=新的无符号字符[m_宽度*m_高度
*m_字节/像素/2];
无符号字符*rgb=m_RawImage;
图像大小=米宽*米高;
大小=图像大小;
尺寸=upos+upos/4;
尺寸i=0;
用于(尺寸线=0;线<米高度;++线){
如果(!(第%2行)){
对于(尺寸x=0;x>8)+16;
目的地[upos++]=(-38*r+-74*g+112*b)>>8)
+ 128;
目的地[vpos++]=((112*r+-94*g+-18*b)>>8)
+ 128;
r=rgb[3*i];
g=rgb[3*i+1];
b=rgb[3*i+2];
目的地[i++]=((66*r+129*g+25*b)>>8)+16;
}
}否则{
对于(尺寸x=0;x>8)+16;
}
}
}
ADKVideoEncoder::getInstance()->startEncodeVideo(目标);
删除[]目的地;
}
void ADKVideoEncoder::startEncodeVideo(无符号字符*原始数据){
AVFormatContext*oc;
AVOutputFormat*fmt;
AVStream*视频;
avc*c;
双视屏;
uint8_t*视频突发事件;
AVFrame*图片;
整数大小;
int ret;
int视频大小;
const char*filename=“/sdcard/test.mpg”;
av_寄存器_all();
fmt=av_guess_格式(空,文件名,空);
oc=avformat_alloc_context();
oc->oformat=fmt;
snprintf(oc->filename,sizeof(oc->filename),“%s”,filename);
视频=空;
如果(fmt->video\u codec!=codec\u ID\u NONE){
视频流=av新流(oc,0);
c=视频->编解码器;
c->codec_id=fmt->video_codec;
c->codec\u type=AVMEDIA\u type\u VIDEO;
c->比特率=400000;
c->宽度=320;
c->高度=480;
c->time_base.num=1;
c->time_base.den=1;
c->gop_尺寸=12;
c->pix_fmt=pix_fmt_YUV420P;
c->max_b_frames=0;
如果(!strcmp(oc->oformat->名称,“mp4”)
||!strcmp(oc->oformat->名称,“mov”)
||!strcmp(oc->oformat->name,“3gp”)){
c->flags |=编解码器|标志|全局|头;
}
}
av_转储_格式(oc,0,文件名,1);
如果(视频){
AVCodec*codec=AVCodec\u find\u编码器(c->codec\u id);
如果(!编解码器){
返回;
}
AVDictionary*选项DICT=NULL;
if(avcodec_open2(c、codec和optionsDict)<0){
返回;
}
如果(!(oc->oformat->flags&AVFMT\U RAWCORMATION)){
视频大小=20000;
视频突发=(uint8\u t*)av\u malloc(视频突发大小);
}
picture=avcodec_alloc_frame();
大小=avpicture\u get\u大小(c->pix\u fmt,c->宽度,c->高度);
avpicture_fill((avpicture*)图片,原始数据,c->pix_fmt,c->宽度,
c->高度);
}
如果(!(fmt->标志和AVFMT_文件)){
如果(avio_打开(&oc->pb,文件名,avio_标志_写入)<0){
返回;
}
}
avformat_write_头(oc,0);
如果(视频){
视频时间=(双精度)(视频时间->时间值*视频时间->时间基数.num
/视频->时基.den);
}否则{
视频_pts=0.0;
}
如果(!video_st/*| video_pts>=5.0*/){
返回;
}
c=视频->编解码器;
尺寸=c->宽度*c->高度;
图片->数据[0]=原始数据;
图片->数据[1]=原始数据+大小;
图片->数据[2]=原始数据+大小*5/4;
如果(oc->oformat->flags和AVFMT_RAWPICTURE){
AVPacket-pkt;
av_初始_数据包(&pkt);
pkt.flags |=AV_pkt_FLAG_键;
pkt.stream\u index=video\u st->index;
pkt.data=(uint8_t*)图片;
pkt.size=sizeof(AVPicture);
ret=av写入帧(oc和pkt);
}否则{
int out_size=avcodec_encode_video(c,video_EXPUF,video_EXPUF_size,
图片);
如果(输出大小>0){
AVPacket-pkt;
av_初始_数据包(&pkt);
pkt.pts=av_rescale_q(c->coded_frame->pts,c->time_base,
视频->时基);
如果(c->编码帧->关键帧){
pkt.flags |=AV_pkt_FLAG_键;
}
pkt.stream\u index=video\u st->index;
pkt.data=video\u exputf;
pkt.size=外部尺寸;
ret=av写入帧(oc和pkt);
}
}
如果(视频){
avcodec_关闭(视频->编解码器);
av_免费(图片);
av_免费(视频_论坛);
}
av_写入_预告片(oc);
对于(inti=0;inb\u流;i++){
av_freep(&oc->streams[i]->codec);
av_freep(&oc->streams[i]);
}
如果(!(fmt->标志和AVFMT_文件)){
avio_关闭(oc->pb);
}
无av_(oc);
}
有人能找出问题所在吗?非常感谢 嗨,你能解释一下吗<代码>图片->数据[0]=原始数据;图片->数据[1]=原始数据+大小;图片->数据[2]=原始数据+大小*5/4代码>为什么使用
5/4
?
void ADKVideoEncoder::startEncodeVideo(unsigned char* rawDatas) {
AVFormatContext* oc;
AVOutputFormat* fmt;
AVStream* video_st;
AVCodecContext* c;
double video_pts;
uint8_t* video_outbuf;
AVFrame* picture;
int size;
int ret;
int video_outbuf_size;
const char* filename = "/sdcard/test.mpg";
av_register_all();
fmt = av_guess_format(NULL, filename, NULL);
oc = avformat_alloc_context();
oc->oformat = fmt;
snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
video_st = NULL;
if (fmt->video_codec != CODEC_ID_NONE) {
video_st = av_new_stream(oc, 0);
c = video_st->codec;
c->codec_id = fmt->video_codec;
c->codec_type = AVMEDIA_TYPE_VIDEO;
c->bit_rate = 400000;
c->width = 320;
c->height = 480;
c->time_base.num = 1;
c->time_base.den = 1;
c->gop_size = 12;
c->pix_fmt = PIX_FMT_YUV420P;
c->max_b_frames = 0;
if (!strcmp(oc->oformat->name, "mp4")
|| !strcmp(oc->oformat->name, "mov")
|| !strcmp(oc->oformat->name, "3gp")) {
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
}
av_dump_format(oc, 0, filename, 1);
if (video_st) {
AVCodec* codec = avcodec_find_encoder(c->codec_id);
if (!codec) {
return;
}
AVDictionary *optionsDict = NULL;
if (avcodec_open2(c, codec, &optionsDict) < 0) {
return;
}
if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
video_outbuf_size = 20000;
video_outbuf = (uint8_t*) av_malloc(video_outbuf_size);
}
picture = avcodec_alloc_frame();
size = avpicture_get_size(c->pix_fmt, c->width, c->height);
avpicture_fill((AVPicture*) picture, rawDatas, c->pix_fmt, c->width,
c->height);
}
if (!(fmt->flags & AVFMT_NOFILE)) {
if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0) {
return;
}
}
avformat_write_header(oc, 0);
if (video_st) {
video_pts = (double) (video_st->pts.val * video_st->time_base.num
/ video_st->time_base.den);
} else {
video_pts = 0.0;
}
if (!video_st/* || video_pts >= 5.0*/) {
return;
}
c = video_st->codec;
size = c->width * c->height;
picture->data[0] = rawDatas;
picture->data[1] = rawDatas + size;
picture->data[2] = rawDatas + size * 5 / 4;
if (oc->oformat->flags & AVFMT_RAWPICTURE) {
AVPacket pkt;
av_init_packet(&pkt);
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index = video_st->index;
pkt.data = (uint8_t*) picture;
pkt.size = sizeof(AVPicture);
ret = av_write_frame(oc, &pkt);
} else {
int out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size,
picture);
if (out_size > 0) {
AVPacket pkt;
av_init_packet(&pkt);
pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base,
video_st->time_base);
if (c->coded_frame->key_frame) {
pkt.flags |= AV_PKT_FLAG_KEY;
}
pkt.stream_index = video_st->index;
pkt.data = video_outbuf;
pkt.size = out_size;
ret = av_write_frame(oc, &pkt);
}
}
if (video_st) {
avcodec_close(video_st->codec);
av_free(picture);
av_free(video_outbuf);
}
av_write_trailer(oc);
for (int i = 0; i < oc->nb_streams; i++) {
av_freep(&oc->streams[i]->codec);
av_freep(&oc->streams[i]);
}
if (!(fmt->flags & AVFMT_NOFILE)) {
avio_close(oc->pb);
}
av_free(oc);