这是我的步骤:
将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
* 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 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);
}
那么有人能找到问题吗?非常感谢!;