diff --git a/libavcodec/aaccoder_twoloop.h b/libavcodec/aaccoder_twoloop.h
index 2cc9a52d739f0426f568e38c1bb273bbd1313c0c..e53257fbaa35b46d9605ef98c87cf7a13b3e711c 100644
--- a/libavcodec/aaccoder_twoloop.h
+++ b/libavcodec/aaccoder_twoloop.h
@@ -142,7 +142,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
          * No need to be overly precise, this only controls RD
          * adjustment CB limits when going overboard
          */
-        if (s->options.stereo_mode && s->cur_type == TYPE_CPE)
+        if (s->options.mid_side && s->cur_type == TYPE_CPE)
             destbits *= 2;
 
         /**
diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c
index 804112700906205484222dcbf2ba31051cc0ce22..78e292b246211ce501a000840ee6dfba3ec95f9b 100644
--- a/libavcodec/aacenc.c
+++ b/libavcodec/aacenc.c
@@ -46,6 +46,44 @@
 
 #include "psymodel.h"
 
+struct AACProfileOptions {
+    int profile;
+    struct AACEncOptions opts;
+};
+
+ /**
+ * List of currently supported profiles, anything not listed isn't supported.
+ */
+static const struct AACProfileOptions aacenc_profiles[] = {
+    {FF_PROFILE_AAC_MAIN,
+        {  /* Main profile, all advanced encoding abilities enabled */
+            .mid_side = 0,
+            .pns = 1,
+            .tns = 0,
+            .pred = OPT_REQUIRED,
+            .intensity_stereo = 1,
+        },
+    },
+    {FF_PROFILE_AAC_LOW,
+        {  /* Default profile, these are the settings that get set by default */
+            .mid_side = 0,
+            .pns = 1,
+            .tns = 0,
+            .pred = OPT_NEEDS_MAIN,
+            .intensity_stereo = 1,
+        },
+    },
+    {FF_PROFILE_MPEG2_AAC_LOW,
+        {  /* Strict MPEG 2 Part 7 compliance profile */
+            .mid_side = 0,
+            .pns = OPT_BANNED,
+            .tns = 0,
+            .pred = OPT_BANNED,
+            .intensity_stereo = 1,
+        },
+    },
+};
+
 /**
  * Make AAC audio config object.
  * @see 1.6.2.1 "Syntax - AudioSpecificConfig"
@@ -690,8 +728,8 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
                 }
                 s->cur_channel = start_ch;
             }
-            if (s->options.stereo_mode) { /* Mid/Side stereo */
-                if (s->options.stereo_mode == -1 && s->coder->search_for_ms)
+            if (s->options.mid_side) { /* Mid/Side stereo */
+                if (s->options.mid_side == -1 && s->coder->search_for_ms)
                     s->coder->search_for_ms(s, cpe);
                 else if (cpe->common_window)
                     memset(cpe->ms_mask, 1, sizeof(cpe->ms_mask));
@@ -852,82 +890,88 @@ alloc_fail:
 static av_cold int aac_encode_init(AVCodecContext *avctx)
 {
     AACEncContext *s = avctx->priv_data;
+    const AACEncOptions *p_opt = NULL;
     int i, ret = 0;
     const uint8_t *sizes[2];
     uint8_t grouping[AAC_MAX_CHANNELS];
     int lengths[2];
 
+    s->channels = avctx->channels;
+    s->chan_map = aac_chan_configs[s->channels-1];
+    s->random_state = 0x1f2e3d4c;
+    s->lambda = avctx->global_quality > 0 ? avctx->global_quality : 120;
+    avctx->extradata_size = 5;
     avctx->frame_size = 1024;
+    avctx->initial_padding = 1024;
+    avctx->bit_rate = (int)FFMIN(
+        6144 * s->channels / 1024.0 * avctx->sample_rate,
+        avctx->bit_rate);
+    avctx->profile = avctx->profile == FF_PROFILE_UNKNOWN ? FF_PROFILE_AAC_LOW :
+                     avctx->profile;
 
     for (i = 0; i < 16; i++)
         if (avctx->sample_rate == avpriv_mpeg4audio_sample_rates[i])
             break;
+    s->samplerate_index = i;
 
-    s->channels = avctx->channels;
-
-    ERROR_IF(i == 16 || i >= ff_aac_swb_size_1024_len || i >= ff_aac_swb_size_128_len,
+    ERROR_IF(s->samplerate_index == 16 ||
+             s->samplerate_index >= ff_aac_swb_size_1024_len ||
+             s->samplerate_index >= ff_aac_swb_size_128_len,
              "Unsupported sample rate %d\n", avctx->sample_rate);
     ERROR_IF(s->channels > AAC_MAX_CHANNELS || s->channels == 7,
              "Unsupported number of channels: %d\n", s->channels);
     WARN_IF(1024.0 * avctx->bit_rate / avctx->sample_rate > 6144 * s->channels,
              "Too many bits per frame requested, clamping to max\n");
-    if (avctx->profile == FF_PROFILE_AAC_MAIN) {
-        s->options.pred = 1;
-    } else if ((avctx->profile == FF_PROFILE_AAC_LOW ||
-                avctx->profile == FF_PROFILE_UNKNOWN) && s->options.pred) {
-        s->profile = 0; /* Main */
-        WARN_IF(1, "Prediction requested, changing profile to AAC-Main\n");
-    } else if (avctx->profile == FF_PROFILE_AAC_LOW ||
-               avctx->profile == FF_PROFILE_UNKNOWN) {
-        s->profile = 1; /* Low */
-    } else {
-        ERROR_IF(1, "Unsupported profile %d\n", avctx->profile);
+
+    for (i = 0; i < FF_ARRAY_ELEMS(aacenc_profiles); i++) {
+        if (avctx->profile == aacenc_profiles[i].profile) {
+            p_opt = &aacenc_profiles[i].opts;
+            break;
+        }
     }
+    ERROR_IF(!p_opt, "Unsupported encoding profile: %d\n", avctx->profile);
+    AAC_OPT_SET(&s->options, p_opt, 1, coder);
+    AAC_OPT_SET(&s->options, p_opt, 0, pns);
+    AAC_OPT_SET(&s->options, p_opt, 0, tns);
+    AAC_OPT_SET(&s->options, p_opt, 0, pred);
+    AAC_OPT_SET(&s->options, p_opt, 1, mid_side);
+    AAC_OPT_SET(&s->options, p_opt, 0, intensity_stereo);
+    if (avctx->profile == FF_PROFILE_MPEG2_AAC_LOW)
+        s->profile = FF_PROFILE_AAC_LOW;
+    else
+        s->profile = avctx->profile;
+    s->coder = &ff_aac_coders[s->options.coder];
 
-    if (s->options.aac_coder != AAC_CODER_TWOLOOP) {
+    if (s->options.coder != AAC_CODER_TWOLOOP) {
         s->options.intensity_stereo = 0;
         s->options.pns = 0;
     }
 
-    avctx->bit_rate = (int)FFMIN(
-        6144 * s->channels / 1024.0 * avctx->sample_rate,
-        avctx->bit_rate);
-
-    s->samplerate_index = i;
-
-    s->chan_map = aac_chan_configs[s->channels-1];
-
     if ((ret = dsp_init(avctx, s)) < 0)
         goto fail;
 
     if ((ret = alloc_buffers(avctx, s)) < 0)
         goto fail;
 
-    avctx->extradata_size = 5;
     put_audio_specific_config(avctx);
 
-    sizes[0]   = ff_aac_swb_size_1024[i];
-    sizes[1]   = ff_aac_swb_size_128[i];
-    lengths[0] = ff_aac_num_swb_1024[i];
-    lengths[1] = ff_aac_num_swb_128[i];
+    sizes[0]   = ff_aac_swb_size_1024[s->samplerate_index];
+    sizes[1]   = ff_aac_swb_size_128[s->samplerate_index];
+    lengths[0] = ff_aac_num_swb_1024[s->samplerate_index];
+    lengths[1] = ff_aac_num_swb_128[s->samplerate_index];
     for (i = 0; i < s->chan_map[0]; i++)
         grouping[i] = s->chan_map[i + 1] == TYPE_CPE;
     if ((ret = ff_psy_init(&s->psy, avctx, 2, sizes, lengths,
                            s->chan_map[0], grouping)) < 0)
         goto fail;
     s->psypp = ff_psy_preprocess_init(avctx);
-    s->coder = &ff_aac_coders[s->options.aac_coder];
     ff_lpc_init(&s->lpc, 2*avctx->frame_size, TNS_MAX_ORDER, FF_LPC_TYPE_LEVINSON);
 
     if (HAVE_MIPSDSPR1)
         ff_aac_coder_init_mips(s);
 
-    s->lambda = avctx->global_quality > 0 ? avctx->global_quality : 120;
-    s->random_state = 0x1f2e3d4c;
-
     ff_aac_tableinit();
 
-    avctx->initial_padding = 1024;
     ff_af_queue_init(avctx, &s->afq);
 
     return 0;
@@ -938,19 +982,16 @@ fail:
 
 #define AACENC_FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
 static const AVOption aacenc_options[] = {
-    {"stereo_mode", "Stereo coding method", offsetof(AACEncContext, options.stereo_mode), AV_OPT_TYPE_INT, {.i64 = 0}, -1, 1, AACENC_FLAGS, "stereo_mode"},
-        {"auto",     "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = -1 }, INT_MIN, INT_MAX, AACENC_FLAGS, "stereo_mode"},
-        {"ms_off",   "Disable Mid/Side coding", 0, AV_OPT_TYPE_CONST, {.i64 =  0 }, INT_MIN, INT_MAX, AACENC_FLAGS, "stereo_mode"},
-        {"ms_force", "Force Mid/Side for the whole frame if possible", 0, AV_OPT_TYPE_CONST, {.i64 =  1 }, INT_MIN, INT_MAX, AACENC_FLAGS, "stereo_mode"},
-    {"aac_coder", "Coding algorithm", offsetof(AACEncContext, options.aac_coder), AV_OPT_TYPE_INT, {.i64 = AAC_CODER_TWOLOOP}, 0, AAC_CODER_NB-1, AACENC_FLAGS, "aac_coder"},
-        {"faac",     "FAAC-inspired method",      0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAAC},    INT_MIN, INT_MAX, AACENC_FLAGS, "aac_coder"},
-        {"anmr",     "ANMR method",               0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_ANMR},    INT_MIN, INT_MAX, AACENC_FLAGS, "aac_coder"},
-        {"twoloop",  "Two loop searching method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_TWOLOOP}, INT_MIN, INT_MAX, AACENC_FLAGS, "aac_coder"},
-        {"fast",     "Constant quantizer",        0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAST},    INT_MIN, INT_MAX, AACENC_FLAGS, "aac_coder"},
-    {"aac_pns", "Perceptual Noise Substitution", offsetof(AACEncContext, options.pns), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AACENC_FLAGS},
-    {"aac_is", "Intensity stereo coding", offsetof(AACEncContext, options.intensity_stereo), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AACENC_FLAGS},
-    {"aac_tns", "Temporal noise shaping", offsetof(AACEncContext, options.tns), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AACENC_FLAGS},
-    {"aac_pred", "AAC-Main prediction", offsetof(AACEncContext, options.pred), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AACENC_FLAGS},
+    {"aac_coder", "Coding algorithm", offsetof(AACEncContext, options.coder), AV_OPT_TYPE_INT, {.i64 = AAC_CODER_TWOLOOP}, -1, AAC_CODER_NB-1, AACENC_FLAGS, "coder"},
+        {"faac",     "FAAC-inspired method",      0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAAC},    INT_MIN, INT_MAX, AACENC_FLAGS, "coder"},
+        {"anmr",     "ANMR method",               0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_ANMR},    INT_MIN, INT_MAX, AACENC_FLAGS, "coder"},
+        {"twoloop",  "Two loop searching method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_TWOLOOP}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"},
+        {"fast",     "Constant quantizer",        0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAST},    INT_MIN, INT_MAX, AACENC_FLAGS, "coder"},
+    {"aac_ms", "Force M/S stereo coding", offsetof(AACEncContext, options.mid_side), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
+    {"aac_is", "Intensity stereo coding", offsetof(AACEncContext, options.intensity_stereo), AV_OPT_TYPE_BOOL, {.i64 = OPT_AUTO}, -1, 1, AACENC_FLAGS},
+    {"aac_pns", "Perceptual noise substitution", offsetof(AACEncContext, options.pns), AV_OPT_TYPE_BOOL, {.i64 = OPT_AUTO}, -1, 1, AACENC_FLAGS},
+    {"aac_tns", "Temporal noise shaping", offsetof(AACEncContext, options.tns), AV_OPT_TYPE_BOOL, {.i64 = OPT_AUTO}, -1, 1, AACENC_FLAGS},
+    {"aac_pred", "AAC-Main prediction", offsetof(AACEncContext, options.pred), AV_OPT_TYPE_BOOL, {.i64 = OPT_AUTO}, -1, 1, AACENC_FLAGS},
     {NULL}
 };
 
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index 98b38a4bdea3171fd19690660b63ab24b7a856dd..b29fdf53073292a279e1426f4ce691e424395537 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -42,11 +42,11 @@ typedef enum AACCoder {
 }AACCoder;
 
 typedef struct AACEncOptions {
-    int stereo_mode;
-    int aac_coder;
+    int coder;
     int pns;
     int tns;
     int pred;
+    int mid_side;
     int intensity_stereo;
 } AACEncOptions;
 
diff --git a/libavcodec/aacenc_utils.h b/libavcodec/aacenc_utils.h
index 16dad63f616a63195ec08ade58bb182a178af4c7..2fbe4c95bdd979e254d2179b938787171bd2d3a7 100644
--- a/libavcodec/aacenc_utils.h
+++ b/libavcodec/aacenc_utils.h
@@ -201,5 +201,43 @@ static inline int lcg_random(unsigned previous_val)
         av_log(avctx, AV_LOG_WARNING, __VA_ARGS__); \
     }
 
+#define AAC_OPT_SET(e_opt, p_opt, bypass, name)                                \
+    ERROR_IF ((e_opt)->name == 1 && (p_opt)->name == OPT_BANNED,               \
+              "Profile %i does not allow %s\n", avctx->profile, #name);        \
+    ERROR_IF ((e_opt)->name == 0 && (p_opt)->name == OPT_REQUIRED,             \
+             "Option %s is a requirement for this profile (%i)\n",             \
+              #name, avctx->profile);                                          \
+    if ((e_opt)->name == 1 && (p_opt)->name == OPT_NEEDS_MAIN &&               \
+        avctx->profile == FF_PROFILE_AAC_LOW) {                                \
+        WARN_IF(1, "Profile %i does not allow for %s, setting profile to "     \
+                "\"aac_main\"(%i)\n", avctx->profile, #name,                   \
+                FF_PROFILE_AAC_MAIN);                                          \
+        avctx->profile = FF_PROFILE_AAC_MAIN;                                  \
+        p_opt = &aacenc_profiles[FF_PROFILE_AAC_MAIN].opts;                    \
+    }                                                                          \
+    if ((e_opt)->name == 1 && (p_opt)->name == OPT_NEEDS_LTP &&                \
+        avctx->profile == FF_PROFILE_AAC_LOW) {                                \
+        WARN_IF(1, "Profile %i does not allow for %s, setting profile to "     \
+                "\"aac_ltp\"(%i)\n", avctx->profile, #name,                    \
+                FF_PROFILE_AAC_LTP);                                           \
+        avctx->profile = FF_PROFILE_AAC_LTP;                                   \
+        p_opt = &aacenc_profiles[FF_PROFILE_AAC_LTP].opts;                     \
+    }                                                                          \
+    if ((e_opt)->name == OPT_AUTO) {                                           \
+        if ((p_opt)->name == OPT_BANNED) {                                     \
+            (e_opt)->name = 0;                                                 \
+        } else if ((p_opt)->name == OPT_NEEDS_LTP) {                           \
+            (e_opt)->name = 0;                                                 \
+        } else if ((p_opt)->name == OPT_NEEDS_MAIN) {                          \
+            (e_opt)->name = 0;                                                 \
+        } else if ((p_opt)->name == OPT_REQUIRED) {                            \
+            (e_opt)->name = 1;                                                 \
+        } else if (bypass) {                                                   \
+            (e_opt)->name = (e_opt)->name;                                     \
+        } else {                                                               \
+            (e_opt)->name = (p_opt)->name;                                     \
+        }                                                                      \
+    }                                                                          \
+    av_log(avctx, AV_LOG_VERBOSE, "Option %s set to %i\n", #name, (e_opt)->name);
 
 #endif /* AVCODEC_AACENC_UTILS_H */
diff --git a/libavcodec/aacenctab.h b/libavcodec/aacenctab.h
index 78b4d400c3b4488bae68b88e309d57fe7c061dd3..c6658a4a6f41204a4eb1258d347f7f7c823ccf85 100644
--- a/libavcodec/aacenctab.h
+++ b/libavcodec/aacenctab.h
@@ -36,6 +36,13 @@
 /** Total number of codebooks, including special ones **/
 #define CB_TOT_ALL 15
 
+/** Profile option settings **/
+#define OPT_AUTO         -1
+#define OPT_BANNED     -256
+#define OPT_NEEDS_LTP  -384
+#define OPT_NEEDS_MAIN -512
+#define OPT_REQUIRED   -768
+
 #define AAC_MAX_CHANNELS 8
 
 extern const uint8_t *ff_aac_swb_size_1024[];